(* ========================================================================= *)
(* Paths, connectedness, homotopy, simple connectedness & contractibility.   *)
(*                                                                           *)
(*              (c) Copyright, John Harrison 1998-2008                       *)
(*              (c) Copyright, Valentina Bruno 2010                          *)
(* ========================================================================= *)

needs "Multivariate/convex.ml";;

(* ------------------------------------------------------------------------- *)
(* Paths and arcs.                                                           *)
(* ------------------------------------------------------------------------- *)

let path = new_definition
 `!g:real^1->real^N. path g <=> g continuous_on interval[vec 0,vec 1]`;;
let pathstart = new_definition
 `pathstart (g:real^1->real^N) = g(vec 0)`;;
let pathfinish = new_definition
 `pathfinish (g:real^1->real^N) = g(vec 1)`;;
let path_image = new_definition
 `path_image (g:real^1->real^N) = IMAGE g (interval[vec 0,vec 1])`;;
let reversepath = new_definition
 `reversepath (g:real^1->real^N) = \x. g(vec 1 - x)`;;
let joinpaths = new_definition
 `(g1 ++ g2) = \x. if drop x <= &1 / &2 then g1(&2 % x)
                   else g2(&2 % x - vec 1)`;;
let simple_path = new_definition
 `simple_path (g:real^1->real^N) <=>
        path g /\
        !x y. x IN interval[vec 0,vec 1] /\
              y IN interval[vec 0,vec 1] /\
              g x = g y
              ==> x = y \/ x = vec 0 /\ y = vec 1 \/ x = vec 1 /\ y = vec 0`;;
let arc = new_definition
 `arc (g:real^1->real^N) <=>
        path g /\
        !x y. x IN interval [vec 0,vec 1] /\
              y IN interval [vec 0,vec 1] /\
              g x = g y
              ==> x = y`;;
(* ------------------------------------------------------------------------- *) (* Invariance theorems. *) (* ------------------------------------------------------------------------- *)
let PATH_EQ = 
prove (`!p q. (!t. t IN interval[vec 0,vec 1] ==> p t = q t) /\ path p ==> path q`,
REWRITE_TAC[path; CONTINUOUS_ON_EQ]);;
let PATH_CONTINUOUS_IMAGE = 
prove (`!f:real^M->real^N g. path g /\ f continuous_on path_image g ==> path(f o g)`,
let PATH_TRANSLATION_EQ = 
prove (`!a g:real^1->real^N. path((\x. a + x) o g) <=> path g`,
REPEAT GEN_TAC THEN REWRITE_TAC[path] THEN EQ_TAC THEN DISCH_TAC THENL [SUBGOAL_THEN `(g:real^1->real^N) = (\x. --a + x) o (\x. a + x) o g` SUBST1_TAC THENL [REWRITE_TAC[FUN_EQ_THM; o_THM] THEN VECTOR_ARITH_TAC; ALL_TAC]; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST]);;
add_translation_invariants [PATH_TRANSLATION_EQ];;
let PATH_LINEAR_IMAGE_EQ = 
prove (`!f:real^M->real^N g. linear f /\ (!x y. f x = f y ==> x = y) ==> (path(f o g) <=> path g)`,
REPEAT GEN_TAC THEN DISCH_TAC THEN FIRST_ASSUM(X_CHOOSE_THEN `h:real^N->real^M` STRIP_ASSUME_TAC o MATCH_MP LINEAR_INJECTIVE_LEFT_INVERSE) THEN REWRITE_TAC[path] THEN EQ_TAC THEN DISCH_TAC THENL [SUBGOAL_THEN `g:real^1->real^M = h o (f:real^M->real^N) o g` SUBST1_TAC THENL [ASM_REWRITE_TAC[o_ASSOC; I_O_ID]; ALL_TAC]; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON]);;
add_linear_invariants [PATH_LINEAR_IMAGE_EQ];;
let PATHSTART_TRANSLATION = 
prove (`!a g. pathstart((\x. a + x) o g) = a + pathstart g`,
REWRITE_TAC[pathstart; o_THM]);;
add_translation_invariants [PATHSTART_TRANSLATION];;
let PATHSTART_LINEAR_IMAGE_EQ = 
prove (`!f g. linear f ==> pathstart(f o g) = f(pathstart g)`,
REWRITE_TAC[pathstart; o_THM]);;
add_linear_invariants [PATHSTART_LINEAR_IMAGE_EQ];;
let PATHFINISH_TRANSLATION = 
prove (`!a g. pathfinish((\x. a + x) o g) = a + pathfinish g`,
REWRITE_TAC[pathfinish; o_THM]);;
add_translation_invariants [PATHFINISH_TRANSLATION];;
let PATHFINISH_LINEAR_IMAGE = 
prove (`!f g. linear f ==> pathfinish(f o g) = f(pathfinish g)`,
REWRITE_TAC[pathfinish; o_THM]);;
add_linear_invariants [PATHFINISH_LINEAR_IMAGE];;
let PATH_IMAGE_TRANSLATION = 
prove (`!a g. path_image((\x. a + x) o g) = IMAGE (\x. a + x) (path_image g)`,
REWRITE_TAC[path_image; IMAGE_o]);;
add_translation_invariants [PATH_IMAGE_TRANSLATION];;
let PATH_IMAGE_LINEAR_IMAGE = 
prove (`!f g. linear f ==> path_image(f o g) = IMAGE f (path_image g)`,
REWRITE_TAC[path_image; IMAGE_o]);;
add_linear_invariants [PATH_IMAGE_LINEAR_IMAGE];;
let REVERSEPATH_TRANSLATION = 
prove (`!a g. reversepath((\x. a + x) o g) = (\x. a + x) o reversepath g`,
REWRITE_TAC[FUN_EQ_THM; reversepath; o_THM]);;
add_translation_invariants [REVERSEPATH_TRANSLATION];;
let REVERSEPATH_LINEAR_IMAGE = 
prove (`!f g. linear f ==> reversepath(f o g) = f o reversepath g`,
REWRITE_TAC[FUN_EQ_THM; reversepath; o_THM]);;
add_linear_invariants [REVERSEPATH_LINEAR_IMAGE];;
let JOINPATHS_TRANSLATION = 
prove (`!a:real^N g1 g2. ((\x. a + x) o g1) ++ ((\x. a + x) o g2) = (\x. a + x) o (g1 ++ g2)`,
REWRITE_TAC[joinpaths; FUN_EQ_THM] THEN REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[o_THM]);;
add_translation_invariants [JOINPATHS_TRANSLATION];;
let JOINPATHS_LINEAR_IMAGE = 
prove (`!f g1 g2. linear f ==> (f o g1) ++ (f o g2) = f o (g1 ++ g2)`,
REWRITE_TAC[joinpaths; FUN_EQ_THM] THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[o_THM]);;
add_linear_invariants [JOINPATHS_LINEAR_IMAGE];;
let SIMPLE_PATH_TRANSLATION_EQ = 
prove (`!a g:real^1->real^N. simple_path((\x. a + x) o g) <=> simple_path g`,
REPEAT GEN_TAC THEN REWRITE_TAC[simple_path; PATH_TRANSLATION_EQ] THEN REWRITE_TAC[o_THM; VECTOR_ARITH `a + x:real^N = a + y <=> x = y`]);;
add_translation_invariants [SIMPLE_PATH_TRANSLATION_EQ];;
let SIMPLE_PATH_LINEAR_IMAGE_EQ = 
prove (`!f:real^M->real^N g. linear f /\ (!x y. f x = f y ==> x = y) ==> (simple_path(f o g) <=> simple_path g)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[simple_path; PATH_TRANSLATION_EQ] THEN BINOP_TAC THENL [ASM_MESON_TAC[PATH_LINEAR_IMAGE_EQ]; ALL_TAC] THEN REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[]);;
add_linear_invariants [SIMPLE_PATH_LINEAR_IMAGE_EQ];;
let ARC_TRANSLATION_EQ = 
prove (`!a g:real^1->real^N. arc((\x. a + x) o g) <=> arc g`,
REPEAT GEN_TAC THEN REWRITE_TAC[arc; PATH_TRANSLATION_EQ] THEN REWRITE_TAC[o_THM; VECTOR_ARITH `a + x:real^N = a + y <=> x = y`]);;
add_translation_invariants [ARC_TRANSLATION_EQ];;
let ARC_LINEAR_IMAGE_EQ = 
prove (`!f:real^M->real^N g. linear f /\ (!x y. f x = f y ==> x = y) ==> (arc(f o g) <=> arc g)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[arc; PATH_TRANSLATION_EQ] THEN BINOP_TAC THENL [ASM_MESON_TAC[PATH_LINEAR_IMAGE_EQ]; ALL_TAC] THEN REWRITE_TAC[o_THM] THEN ASM_MESON_TAC[]);;
add_linear_invariants [ARC_LINEAR_IMAGE_EQ];; (* ------------------------------------------------------------------------- *) (* Basic lemmas about paths. *) (* ------------------------------------------------------------------------- *)
let ARC_IMP_SIMPLE_PATH = 
prove (`!g. arc g ==> simple_path g`,
REWRITE_TAC[arc; simple_path] THEN MESON_TAC[]);;
let ARC_IMP_PATH = 
prove (`!g. arc g ==> path g`,
REWRITE_TAC[arc] THEN MESON_TAC[]);;
let SIMPLE_PATH_IMP_PATH = 
prove (`!g. simple_path g ==> path g`,
REWRITE_TAC[simple_path] THEN MESON_TAC[]);;
let SIMPLE_PATH_CASES = 
prove (`!g:real^1->real^N. simple_path g ==> arc g \/ pathfinish g = pathstart g`,
REWRITE_TAC[simple_path; arc; pathfinish; pathstart] THEN REPEAT STRIP_TAC THEN ASM_CASES_TAC `(g:real^1->real^N) (vec 0) = g(vec 1)` THEN ASM_REWRITE_TAC[] THEN MAP_EVERY X_GEN_TAC [`u:real^1`; `v:real^1`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^1`; `v:real^1`]) THEN ASM_MESON_TAC[]);;
let SIMPLE_PATH_IMP_ARC = 
prove (`!g:real^1->real^N. simple_path g /\ ~(pathfinish g = pathstart g) ==> arc g`,
MESON_TAC[SIMPLE_PATH_CASES]);;
let ARC_DISTINCT_ENDS = 
prove (`!g:real^1->real^N. arc g ==> ~(pathfinish g = pathstart g)`,
GEN_TAC THEN REWRITE_TAC[arc; pathfinish; pathstart] THEN ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> a /\ b /\ ~d ==> ~c`] THEN DISCH_THEN(MATCH_MP_TAC o CONJUNCT2) THEN REWRITE_TAC[GSYM DROP_EQ; IN_INTERVAL_1; DROP_VEC] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let ARC_SIMPLE_PATH = 
prove (`!g:real^1->real^N. arc g <=> simple_path g /\ ~(pathfinish g = pathstart g)`,
let SIMPLE_PATH_EQ_ARC = 
prove (`!g. ~(pathstart g = pathfinish g) ==> (simple_path g <=> arc g)`,
SIMP_TAC[ARC_SIMPLE_PATH]);;
let PATH_IMAGE_NONEMPTY = 
prove (`!g. ~(path_image g = {})`,
let PATHSTART_IN_PATH_IMAGE = 
prove (`!g. (pathstart g) IN path_image g`,
GEN_TAC THEN REWRITE_TAC[pathstart; path_image] THEN MATCH_MP_TAC FUN_IN_IMAGE THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS]);;
let PATHFINISH_IN_PATH_IMAGE = 
prove (`!g. (pathfinish g) IN path_image g`,
GEN_TAC THEN REWRITE_TAC[pathfinish; path_image] THEN MATCH_MP_TAC FUN_IN_IMAGE THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN REAL_ARITH_TAC);;
let CONNECTED_PATH_IMAGE = 
prove (`!g. path g ==> connected(path_image g)`,
REWRITE_TAC[path; path_image] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_SIMP_TAC[CONVEX_CONNECTED; CONVEX_INTERVAL]);;
let COMPACT_PATH_IMAGE = 
prove (`!g. path g ==> compact(path_image g)`,
REWRITE_TAC[path; path_image] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[COMPACT_INTERVAL]);;
let BOUNDED_PATH_IMAGE = 
prove (`!g. path g ==> bounded(path_image g)`,
let CLOSED_PATH_IMAGE = 
prove (`!g. path g ==> closed(path_image g)`,
let CONNECTED_SIMPLE_PATH_IMAGE = 
prove (`!g. simple_path g ==> connected(path_image g)`,
let COMPACT_SIMPLE_PATH_IMAGE = 
prove (`!g. simple_path g ==> compact(path_image g)`,
let BOUNDED_SIMPLE_PATH_IMAGE = 
prove (`!g. simple_path g ==> bounded(path_image g)`,
let CLOSED_SIMPLE_PATH_IMAGE = 
prove (`!g. simple_path g ==> closed(path_image g)`,
let CONNECTED_ARC_IMAGE = 
prove (`!g. arc g ==> connected(path_image g)`,
let COMPACT_ARC_IMAGE = 
prove (`!g. arc g ==> compact(path_image g)`,
let BOUNDED_ARC_IMAGE = 
prove (`!g. arc g ==> bounded(path_image g)`,
let CLOSED_ARC_IMAGE = 
prove (`!g. arc g ==> closed(path_image g)`,
let PATHSTART_COMPOSE = 
prove (`!f p. pathstart(f o p) = f(pathstart p)`,
REWRITE_TAC[pathstart; o_THM]);;
let PATHFINISH_COMPOSE = 
prove (`!f p. pathfinish(f o p) = f(pathfinish p)`,
REWRITE_TAC[pathfinish; o_THM]);;
let PATH_IMAGE_COMPOSE = 
prove (`!f p. path_image (f o p) = IMAGE f (path_image p)`,
REWRITE_TAC[path_image; IMAGE_o]);;
let PATH_COMPOSE_JOIN = 
prove (`!f p q. f o (p ++ q) = (f o p) ++ (f o q)`,
REWRITE_TAC[joinpaths; o_DEF; FUN_EQ_THM] THEN MESON_TAC[]);;
let PATH_COMPOSE_REVERSEPATH = 
prove (`!f p. f o reversepath p = reversepath(f o p)`,
REWRITE_TAC[reversepath; o_DEF; FUN_EQ_THM] THEN MESON_TAC[]);;
let JOIN_PATHS_EQ = 
prove (`!p q:real^1->real^N. (!t. t IN interval[vec 0,vec 1] ==> p t = p' t) /\ (!t. t IN interval[vec 0,vec 1] ==> q t = q' t) ==> !t. t IN interval[vec 0,vec 1] ==> (p ++ q) t = (p' ++ q') t`,
REWRITE_TAC[joinpaths; IN_INTERVAL_1; DROP_VEC] THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[IN_INTERVAL_1; DROP_CMUL; DROP_SUB; DROP_VEC] THEN ASM_REAL_ARITH_TAC);;
let CARD_EQ_SIMPLE_PATH_IMAGE = 
prove (`!g. simple_path g ==> path_image g =_c (:real)`,
SIMP_TAC[CONNECTED_CARD_EQ_IFF_NONTRIVIAL; CONNECTED_SIMPLE_PATH_IMAGE] THEN GEN_TAC THEN REWRITE_TAC[simple_path; path_image] THEN MATCH_MP_TAC(SET_RULE `(?u v. u IN s /\ v IN s /\ ~(u = a) /\ ~(v = a) /\ ~(u = v)) ==> P /\ (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y \/ x = a /\ y = b \/ x = b /\ y = a) ==> ~(?c. IMAGE f s SUBSET {c})`) THEN MAP_EVERY EXISTS_TAC [`lift(&1 / &3)`; `lift(&1 / &2)`] THEN REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP; GSYM LIFT_NUM; LIFT_EQ] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let INFINITE_SIMPLE_PATH_IMAGE = 
prove (`!g. simple_path g ==> INFINITE(path_image g)`,
let CARD_EQ_ARC_IMAGE = 
prove (`!g. arc g ==> path_image g =_c (:real)`,
let INFINITE_ARC_IMAGE = 
prove (`!g. arc g ==> INFINITE(path_image g)`,
(* ------------------------------------------------------------------------- *) (* Simple paths with the endpoints removed. *) (* ------------------------------------------------------------------------- *)
let SIMPLE_PATH_ENDLESS = 
prove (`!c:real^1->real^N. simple_path c ==> path_image c DIFF {pathstart c,pathfinish c} = IMAGE c (interval(vec 0,vec 1))`,
REWRITE_TAC[simple_path; path_image; pathstart; pathfinish] THEN REWRITE_TAC[OPEN_CLOSED_INTERVAL_1; path] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC(SET_RULE `(!x y. x IN s /\ y IN s /\ c x = c y ==> x = y \/ x = a /\ y = b \/ x = b /\ y = a) /\ a IN s /\ b IN s ==> IMAGE c s DIFF {c a,c b} = IMAGE c (s DIFF {a,b})`) THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS; REAL_LE_REFL]);;
let CONNECTED_SIMPLE_PATH_ENDLESS = 
prove (`!c:real^1->real^N. simple_path c ==> connected(path_image c DIFF {pathstart c,pathfinish c})`,
REPEAT STRIP_TAC THEN ASM_SIMP_TAC[SIMPLE_PATH_ENDLESS] THEN MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN SIMP_TAC[CONVEX_INTERVAL; CONVEX_CONNECTED] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN RULE_ASSUM_TAC(REWRITE_RULE[simple_path; path]) THEN ASM_REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED]);;
let NONEMPTY_SIMPLE_PATH_ENDLESS = 
prove (`!c:real^1->real^N. simple_path c ==> ~(path_image c DIFF {pathstart c,pathfinish c} = {})`,
SIMP_TAC[SIMPLE_PATH_ENDLESS; IMAGE_EQ_EMPTY; INTERVAL_EQ_EMPTY_1] THEN REWRITE_TAC[DROP_VEC] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* The operations on paths. *) (* ------------------------------------------------------------------------- *)
let JOINPATHS = 
prove (`!g1 g2. pathfinish g1 = pathstart g2 ==> g1 ++ g2 = \x. if drop x < &1 / &2 then g1(&2 % x) else g2 (&2 % x - vec 1)`,
REWRITE_TAC[pathstart; pathfinish] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[joinpaths; FUN_EQ_THM] THEN X_GEN_TAC `x:real^1` THEN ASM_CASES_TAC `drop x = &1 / &2` THENL [FIRST_X_ASSUM(MP_TAC o AP_TERM `lift`) THEN REWRITE_TAC[LIFT_DROP] THEN DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[LIFT_DROP; REAL_LE_REFL; GSYM LIFT_CMUL; REAL_LT_REFL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[LIFT_NUM; VECTOR_SUB_REFL]; REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN ASM_REAL_ARITH_TAC]);;
let REVERSEPATH_REVERSEPATH = 
prove (`!g:real^1->real^N. reversepath(reversepath g) = g`,
REWRITE_TAC[reversepath; ETA_AX; VECTOR_ARITH `vec 1 - (vec 1 - x):real^1 = x`]);;
let PATHSTART_REVERSEPATH = 
prove (`pathstart(reversepath g) = pathfinish g`,
let PATHFINISH_REVERSEPATH = 
prove (`pathfinish(reversepath g) = pathstart g`,
let PATHSTART_JOIN = 
prove (`!g1 g2. pathstart(g1 ++ g2) = pathstart g1`,
REWRITE_TAC[joinpaths; pathstart; pathstart; DROP_VEC; VECTOR_MUL_RZERO] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let PATHFINISH_JOIN = 
prove (`!g1 g2. pathfinish(g1 ++ g2) = pathfinish g2`,
REPEAT GEN_TAC THEN REWRITE_TAC[joinpaths; pathfinish; DROP_VEC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN AP_TERM_TAC THEN VECTOR_ARITH_TAC);;
let PATH_IMAGE_REVERSEPATH = 
prove (`!g:real^1->real^N. path_image(reversepath g) = path_image g`,
SUBGOAL_THEN `!g:real^1->real^N. path_image(reversepath g) SUBSET path_image g` (fun th -> MESON_TAC[th; REVERSEPATH_REVERSEPATH; SUBSET_ANTISYM]) THEN REWRITE_TAC[SUBSET; path_image; FORALL_IN_IMAGE] THEN MAP_EVERY X_GEN_TAC [`g:real^1->real^N`; `x:real^1`] THEN DISCH_TAC THEN REWRITE_TAC[reversepath; IN_IMAGE] THEN EXISTS_TAC `vec 1 - x:real^1` THEN POP_ASSUM MP_TAC THEN REWRITE_TAC[IN_INTERVAL_1; DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC);;
let PATH_REVERSEPATH = 
prove (`!g:real^1->real^N. path(reversepath g) <=> path g`,
SUBGOAL_THEN `!g:real^1->real^N. path g ==> path(reversepath g)` (fun th -> MESON_TAC[th; REVERSEPATH_REVERSEPATH]) THEN GEN_TAC THEN REWRITE_TAC[path; reversepath] THEN STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1] THEN REWRITE_TAC[DROP_VEC; DROP_SUB] THEN REAL_ARITH_TAC);;
let PATH_JOIN = 
prove (`!g1 g2:real^1->real^N. pathfinish g1 = pathstart g2 ==> (path(g1 ++ g2) <=> path g1 /\ path g2)`,
REWRITE_TAC[path; pathfinish; pathstart] THEN REPEAT STRIP_TAC THEN EQ_TAC THENL [STRIP_TAC THEN CONJ_TAC THENL [SUBGOAL_THEN `(g1:real^1->real^N) = (\x. g1 (&2 % x)) o (\x. &1 / &2 % x)` SUBST1_TAC THENL [REWRITE_TAC[FUN_EQ_THM; o_THM] THEN GEN_TAC THEN AP_TERM_TAC THEN VECTOR_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID] THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THEN EXISTS_TAC `(g1 ++ g2):real^1->real^N` THEN CONJ_TAC THENL [REWRITE_TAC[FORALL_IN_IMAGE; joinpaths; IN_INTERVAL_1; DROP_CMUL] THEN SIMP_TAC[DROP_VEC; REAL_ARITH `&1 / &2 * x <= &1 / &2 <=> x <= &1`]; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; DROP_CMUL] THEN REWRITE_TAC[DROP_VEC] THEN REAL_ARITH_TAC; SUBGOAL_THEN `(g2:real^1->real^N) = (\x. g2 (&2 % x - vec 1)) o (\x. &1 / &2 % (x + vec 1))` SUBST1_TAC THENL [REWRITE_TAC[FUN_EQ_THM; o_THM] THEN GEN_TAC THEN AP_TERM_TAC THEN VECTOR_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ADD] THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THEN EXISTS_TAC `(g1 ++ g2):real^1->real^N` THEN CONJ_TAC THENL [REWRITE_TAC[FORALL_IN_IMAGE; joinpaths; IN_INTERVAL_1; DROP_CMUL] THEN REWRITE_TAC[DROP_VEC; DROP_ADD; REAL_ARITH `&1 / &2 * (x + &1) <= &1 / &2 <=> x <= &0`] THEN SIMP_TAC[REAL_ARITH `&0 <= x ==> (x <= &0 <=> x = &0)`; LIFT_NUM; VECTOR_MUL_ASSOC; GSYM LIFT_EQ; LIFT_DROP; GSYM LIFT_CMUL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[VECTOR_ADD_LID; VECTOR_MUL_LID] THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[VECTOR_ARITH `(x + vec 1) - vec 1 = x`]; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; DROP_CMUL] THEN REWRITE_TAC[DROP_VEC; DROP_ADD] THEN REAL_ARITH_TAC]; STRIP_TAC THEN SUBGOAL_THEN `interval[vec 0,vec 1] = interval[vec 0,lift(&1 / &2)] UNION interval[lift(&1 / &2),vec 1]` SUBST1_TAC THENL [SIMP_TAC[EXTENSION; IN_UNION; IN_INTERVAL_1; LIFT_DROP; DROP_VEC] THEN REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_UNION THEN REWRITE_TAC[CLOSED_INTERVAL] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL [EXISTS_TAC `\x. (g1:real^1->real^N) (&2 % x)`; EXISTS_TAC `\x. (g2:real^1->real^N) (&2 % x - vec 1)`] THEN REWRITE_TAC[joinpaths] THEN SIMP_TAC[IN_INTERVAL_1; LIFT_DROP] THENL [GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID] THEN ONCE_REWRITE_TAC[VECTOR_ARITH `&2 % (x:real^1) = &2 % x + vec 0`] THEN REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN REWRITE_TAC[REAL_POS; INTERVAL_EQ_EMPTY_1; LIFT_DROP; DROP_VEC] THEN REWRITE_TAC[GSYM LIFT_CMUL; VECTOR_ADD_RID; VECTOR_MUL_RZERO] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[LIFT_NUM]; ALL_TAC] THEN CONJ_TAC THENL [SIMP_TAC[REAL_ARITH `&1 / &2 <= x ==> (x <= &1 / &2 <=> x = &1 / &2)`; GSYM LIFT_EQ; LIFT_DROP; GSYM LIFT_CMUL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish]) THEN ASM_REWRITE_TAC[LIFT_NUM] THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM LIFT_CMUL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LIFT_NUM; VECTOR_SUB_REFL]; ALL_TAC] THEN GEN_REWRITE_TAC LAND_CONV [GSYM o_DEF] THEN MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN ONCE_REWRITE_TAC[VECTOR_ARITH `&2 % x - vec 1 = &2 % x + --vec 1`] THEN REWRITE_TAC[IMAGE_AFFINITY_INTERVAL] THEN REWRITE_TAC[REAL_POS; INTERVAL_EQ_EMPTY_1; LIFT_DROP; DROP_VEC] THEN REWRITE_TAC[GSYM LIFT_CMUL; VECTOR_ADD_RID; VECTOR_MUL_RZERO] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[LIFT_NUM] THEN ASM_REWRITE_TAC[VECTOR_ARITH `&2 % x + --x = x /\ x + --x = vec 0`]]);;
let PATH_JOIN_IMP = 
prove (`!g1 g2:real^1->real^N. path g1 /\ path g2 /\ pathfinish g1 = pathstart g2 ==> path(g1 ++ g2)`,
MESON_TAC[PATH_JOIN]);;
let PATH_IMAGE_JOIN_SUBSET = 
prove (`!g1 g2:real^1->real^N. path_image(g1 ++ g2) SUBSET (path_image g1 UNION path_image g2)`,
REWRITE_TAC[path_image; FORALL_IN_IMAGE; SUBSET] THEN GEN_TAC THEN GEN_TAC THEN X_GEN_TAC `x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; IN_UNION; IN_IMAGE; DROP_VEC; joinpaths] THEN STRIP_TAC THEN ASM_CASES_TAC `drop x <= &1 / &2` THEN ASM_REWRITE_TAC[] THENL [DISJ1_TAC THEN EXISTS_TAC `&2 % x:real^1` THEN REWRITE_TAC[DROP_CMUL]; DISJ2_TAC THEN EXISTS_TAC `&2 % x - vec 1:real^1` THEN REWRITE_TAC[DROP_CMUL; DROP_SUB; DROP_VEC]] THEN ASM_REAL_ARITH_TAC);;
let SUBSET_PATH_IMAGE_JOIN = 
prove (`!g1 g2:real^1->real^N s. path_image g1 SUBSET s /\ path_image g2 SUBSET s ==> path_image(g1 ++ g2) SUBSET s`,
MP_TAC PATH_IMAGE_JOIN_SUBSET THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN SET_TAC[]);;
let PATH_IMAGE_JOIN = 
prove (`!g1 g2. pathfinish g1 = pathstart g2 ==> path_image(g1 ++ g2) = path_image g1 UNION path_image g2`,
REWRITE_TAC[pathfinish; pathstart] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[PATH_IMAGE_JOIN_SUBSET] THEN REWRITE_TAC[path_image; SUBSET; FORALL_AND_THM; IN_UNION; TAUT `a \/ b ==> c <=> (a ==> c) /\ (b ==> c)`] THEN REWRITE_TAC[FORALL_IN_IMAGE; joinpaths] THEN REWRITE_TAC[IN_INTERVAL_1; IN_IMAGE; DROP_VEC] THEN CONJ_TAC THEN X_GEN_TAC `x:real^1` THEN REPEAT STRIP_TAC THENL [EXISTS_TAC `(&1 / &2) % x:real^1` THEN ASM_REWRITE_TAC[DROP_CMUL; REAL_ARITH `&1 / &2 * x <= &1 / &2 <=> x <= &1`] THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[VECTOR_MUL_LID]; EXISTS_TAC `(&1 / &2) % (x + vec 1):real^1` THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_ADD; DROP_VEC] THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[VECTOR_MUL_LID; VECTOR_ARITH `(x + vec 1) - vec 1 = x`] THEN ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> (&1 / &2 * (x + &1) <= &1 / &2 <=> x = &0)`] THEN REWRITE_TAC[GSYM LIFT_EQ; LIFT_DROP; LIFT_NUM] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[VECTOR_ADD_LID; DROP_VEC]] THEN ASM_REAL_ARITH_TAC);;
let NOT_IN_PATH_IMAGE_JOIN = 
prove (`!g1 g2 x. ~(x IN path_image g1) /\ ~(x IN path_image g2) ==> ~(x IN path_image(g1 ++ g2))`,
let ARC_REVERSEPATH = 
prove (`!g. arc g ==> arc(reversepath g)`,
GEN_TAC THEN SIMP_TAC[arc; PATH_REVERSEPATH] THEN REWRITE_TAC[arc; reversepath] THEN STRIP_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`vec 1 - x:real^1`; `vec 1 - y:real^1`]) THEN ASM_REWRITE_TAC[] THEN REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ; DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC);;
let SIMPLE_PATH_REVERSEPATH = 
prove (`!g. simple_path g ==> simple_path (reversepath g)`,
GEN_TAC THEN SIMP_TAC[simple_path; PATH_REVERSEPATH] THEN REWRITE_TAC[simple_path; reversepath] THEN STRIP_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`vec 1 - x:real^1`; `vec 1 - y:real^1`]) THEN ASM_REWRITE_TAC[] THEN REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ; DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC);;
let SIMPLE_PATH_JOIN_LOOP = 
prove (`!g1 g2:real^1->real^N. arc g1 /\ arc g2 /\ pathfinish g1 = pathstart g2 /\ pathfinish g2 = pathstart g1 /\ (path_image g1 INTER path_image g2) SUBSET {pathstart g1,pathstart g2} ==> simple_path(g1 ++ g2)`,
REPEAT GEN_TAC THEN REWRITE_TAC[arc; simple_path] THEN MATCH_MP_TAC(TAUT `(a /\ b /\ c /\ d ==> f) /\ (a' /\ b' /\ c /\ d /\ e ==> g) ==> (a /\ a') /\ (b /\ b') /\ c /\ d /\ e ==> f /\ g`) THEN CONJ_TAC THENL [MESON_TAC[PATH_JOIN]; ALL_TAC] THEN REWRITE_TAC[arc; simple_path; SUBSET; IN_INTER; pathstart; pathfinish; IN_INTERVAL_1; DROP_VEC; IN_INSERT; NOT_IN_EMPTY] THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "G1") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "G2") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "G0")) THEN MATCH_MP_TAC DROP_WLOG_LE THEN CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[joinpaths] THEN MAP_EVERY ASM_CASES_TAC [`drop x <= &1 / &2`; `drop y <= &1 / &2`] THEN ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THENL [REMOVE_THEN "G1" (MP_TAC o SPECL [`&2 % x:real^1`; `&2 % y:real^1`]) THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_VEC; DROP_SUB] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN DISCH_THEN(fun th -> DISJ1_TAC THEN MP_TAC th) THEN VECTOR_ARITH_TAC; ALL_TAC; ASM_REAL_ARITH_TAC; REMOVE_THEN "G2" (MP_TAC o SPECL [`&2 % x:real^1 - vec 1`; `&2 % y:real^1 - vec 1`]) THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_VEC; DROP_SUB] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN DISCH_THEN(fun th -> DISJ1_TAC THEN MP_TAC th) THEN VECTOR_ARITH_TAC] THEN REMOVE_THEN "G0" (MP_TAC o SPEC `(g1:real^1->real^N) (&2 % x)`) THEN ANTS_TAC THENL [CONJ_TAC THENL [REWRITE_TAC[path_image; IN_IMAGE] THEN EXISTS_TAC `&2 % x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_CMUL] THEN ASM_REAL_ARITH_TAC; ASM_REWRITE_TAC[path_image; IN_IMAGE] THEN EXISTS_TAC `&2 % y:real^1 - vec 1` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_CMUL; DROP_SUB] THEN ASM_REAL_ARITH_TAC]; ALL_TAC] THEN STRIP_TAC THENL [DISJ2_TAC THEN DISJ1_TAC; DISJ1_TAC THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `&1 / &2 % vec 1:real^1`] THEN MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL [SUBGOAL_THEN `&2 % x:real^1 = vec 0` MP_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN REMOVE_THEN "G1" MATCH_MP_TAC; DISCH_THEN SUBST_ALL_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[VECTOR_MUL_RZERO]) THEN UNDISCH_TAC `T` THEN REWRITE_TAC[] THEN SUBGOAL_THEN `&2 % y:real^1 - vec 1 = vec 1` MP_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN REMOVE_THEN "G2" MATCH_MP_TAC; SUBGOAL_THEN `&2 % x:real^1 = vec 1` MP_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN REMOVE_THEN "G1" MATCH_MP_TAC; DISCH_THEN SUBST_ALL_TAC THEN SUBGOAL_THEN `&2 % y:real^1 - vec 1 = vec 0` MP_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN REMOVE_THEN "G2" MATCH_MP_TAC] THEN (REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_SUB; DROP_VEC] THEN ASM_REAL_ARITH_TAC));;
let ARC_JOIN = 
prove (`!g1 g2:real^1->real^N. arc g1 /\ arc g2 /\ pathfinish g1 = pathstart g2 /\ (path_image g1 INTER path_image g2) SUBSET {pathstart g2} ==> arc(g1 ++ g2)`,
REPEAT GEN_TAC THEN REWRITE_TAC[arc; simple_path] THEN MATCH_MP_TAC(TAUT `(a /\ b /\ c /\ d ==> f) /\ (a' /\ b' /\ c /\ d ==> g) ==> (a /\ a') /\ (b /\ b') /\ c /\ d ==> f /\ g`) THEN CONJ_TAC THENL [MESON_TAC[PATH_JOIN]; ALL_TAC] THEN REWRITE_TAC[arc; simple_path; SUBSET; IN_INTER; pathstart; pathfinish; IN_INTERVAL_1; DROP_VEC; IN_INSERT; NOT_IN_EMPTY] THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "G1") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "G2") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "G0")) THEN MATCH_MP_TAC DROP_WLOG_LE THEN CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[joinpaths] THEN MAP_EVERY ASM_CASES_TAC [`drop x <= &1 / &2`; `drop y <= &1 / &2`] THEN ASM_REWRITE_TAC[] THEN REPEAT STRIP_TAC THENL [REMOVE_THEN "G1" (MP_TAC o SPECL [`&2 % x:real^1`; `&2 % y:real^1`]) THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_VEC; DROP_SUB] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN VECTOR_ARITH_TAC; ALL_TAC; ASM_REAL_ARITH_TAC; REMOVE_THEN "G2" (MP_TAC o SPECL [`&2 % x:real^1 - vec 1`; `&2 % y:real^1 - vec 1`]) THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_VEC; DROP_SUB] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN VECTOR_ARITH_TAC] THEN REMOVE_THEN "G0" (MP_TAC o SPEC `(g1:real^1->real^N) (&2 % x)`) THEN ANTS_TAC THENL [CONJ_TAC THENL [REWRITE_TAC[path_image; IN_IMAGE] THEN EXISTS_TAC `&2 % x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_CMUL] THEN ASM_REAL_ARITH_TAC; ASM_REWRITE_TAC[path_image; IN_IMAGE] THEN EXISTS_TAC `&2 % y:real^1 - vec 1` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_CMUL; DROP_SUB] THEN ASM_REAL_ARITH_TAC]; ALL_TAC] THEN STRIP_TAC THEN SUBGOAL_THEN `x:real^1 = &1 / &2 % vec 1` SUBST_ALL_TAC THENL [SUBGOAL_THEN `&2 % x:real^1 = vec 1` MP_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN REMOVE_THEN "G1" MATCH_MP_TAC; SUBGOAL_THEN `&2 % y:real^1 - vec 1 = vec 0` MP_TAC THENL [ALL_TAC; VECTOR_ARITH_TAC] THEN REMOVE_THEN "G2" MATCH_MP_TAC] THEN (REWRITE_TAC[CONJ_ASSOC] THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN ASM_REWRITE_TAC[DROP_CMUL; DROP_SUB; DROP_VEC] THEN ASM_REAL_ARITH_TAC));;
let REVERSEPATH_JOINPATHS = 
prove (`!g1 g2. pathfinish g1 = pathstart g2 ==> reversepath(g1 ++ g2) = reversepath g2 ++ reversepath g1`,
REPEAT GEN_TAC THEN REWRITE_TAC[reversepath; joinpaths; pathfinish; pathstart; FUN_EQ_THM] THEN DISCH_TAC THEN X_GEN_TAC `t:real^1` THEN REWRITE_TAC[DROP_VEC; DROP_SUB; REAL_ARITH `&1 - x <= &1 / &2 <=> &1 / &2 <= x`] THEN ASM_CASES_TAC `t = lift(&1 / &2)` THENL [ASM_REWRITE_TAC[LIFT_DROP; REAL_LE_REFL; GSYM LIFT_NUM; GSYM LIFT_SUB; GSYM LIFT_CMUL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[LIFT_NUM]; FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [GSYM DROP_EQ]) THEN REWRITE_TAC[LIFT_DROP] THEN DISCH_TAC THEN ASM_SIMP_TAC[REAL_ARITH `~(x = &1 / &2) ==> (&1 / &2 <= x <=> ~(x <= &1 / &2))`] THEN ASM_CASES_TAC `drop t <= &1 / &2` THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN REWRITE_TAC[VECTOR_SUB_LDISTRIB] THEN VECTOR_ARITH_TAC]);;
(* ------------------------------------------------------------------------- *) (* Some reversed and "if and only if" versions of joining theorems. *) (* ------------------------------------------------------------------------- *)
let PATH_JOIN_PATH_ENDS = 
prove (`!g1 g2:real^1->real^N. path g2 /\ path(g1 ++ g2) ==> pathfinish g1 = pathstart g2`,
REPEAT GEN_TAC THEN DISJ_CASES_TAC(NORM_ARITH `pathfinish g1:real^N = pathstart g2 \/ &0 < dist(pathfinish g1,pathstart g2)`) THEN ASM_REWRITE_TAC[path; continuous_on; joinpaths] THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish]) THEN REWRITE_TAC[pathstart; pathfinish] THEN ABBREV_TAC `e = dist((g1:real^1->real^N)(vec 1),g2(vec 0:real^1))` THEN DISCH_THEN(CONJUNCTS_THEN2 (MP_TAC o SPEC `vec 0:real^1`) (MP_TAC o SPEC `lift(&1 / &2)`)) THEN REWRITE_TAC[ENDS_IN_UNIT_INTERVAL; LIFT_DROP; REAL_LE_REFL] THEN REWRITE_TAC[GSYM LIFT_CMUL; IN_INTERVAL_1; DROP_VEC; LIFT_DROP] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LIFT_NUM] THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN DISCH_THEN(X_CHOOSE_THEN `d1:real` (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "1"))) THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN DISCH_THEN(X_CHOOSE_THEN `d2:real` (CONJUNCTS_THEN2 ASSUME_TAC (LABEL_TAC "2"))) THEN REMOVE_THEN "2" (MP_TAC o SPEC `lift(min (&1 / &2) (min d1 d2) / &2)`) THEN REWRITE_TAC[LIFT_DROP; DIST_LIFT; DIST_0; NORM_REAL; GSYM drop] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN REMOVE_THEN "1" (MP_TAC o SPEC `lift(&1 / &2 + min (&1 / &2) (min d1 d2) / &4)`) THEN REWRITE_TAC[LIFT_DROP; DIST_LIFT] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN COND_CASES_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[GSYM LIFT_CMUL; LIFT_ADD; REAL_ADD_LDISTRIB] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LIFT_NUM] THEN REWRITE_TAC[VECTOR_ADD_SUB; REAL_ARITH `&2 * x / &4 = x / &2`] THEN REPEAT(POP_ASSUM MP_TAC) THEN NORM_ARITH_TAC);;
let PATH_JOIN_EQ = 
prove (`!g1 g2:real^1->real^N. path g1 /\ path g2 ==> (path(g1 ++ g2) <=> pathfinish g1 = pathstart g2)`,
let SIMPLE_PATH_JOIN_IMP = 
prove (`!g1 g2:real^1->real^N. simple_path(g1 ++ g2) /\ pathfinish g1 = pathstart g2 ==> arc g1 /\ arc g2 /\ path_image g1 INTER path_image g2 SUBSET {pathstart g1, pathstart g2}`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `path(g1:real^1->real^N) /\ path(g2:real^1->real^N)` THENL [ALL_TAC; ASM_MESON_TAC[PATH_JOIN; SIMPLE_PATH_IMP_PATH]] THEN REWRITE_TAC[simple_path; pathstart; pathfinish; arc] THEN STRIP_TAC THEN REPEAT CONJ_TAC THEN ASM_REWRITE_TAC[] THENL [MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`&1 / &2 % x:real^1`; `&1 / &2 % y:real^1`]) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; joinpaths; DROP_CMUL] THEN REPEAT(COND_CASES_TAC THEN TRY ASM_REAL_ARITH_TAC) THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; VECTOR_MUL_LID; DROP_VEC] THEN ASM_REAL_ARITH_TAC; MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`&1 / &2 % (x + vec 1):real^1`; `&1 / &2 % (y + vec 1):real^1`]) THEN ASM_SIMP_TAC[JOINPATHS; pathstart; pathfinish] THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_ADD; DROP_CMUL] THEN REPEAT(COND_CASES_TAC THEN TRY ASM_REAL_ARITH_TAC) THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_REWRITE_TAC[VECTOR_MUL_LID; VECTOR_ARITH `(a + b) - b:real^N = a`] THEN ASM_REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; VECTOR_MUL_LID; DROP_VEC; DROP_ADD] THEN ASM_REAL_ARITH_TAC; REWRITE_TAC[SET_RULE `s INTER t SUBSET u <=> !x. x IN s ==> x IN t ==> x IN u`] THEN REWRITE_TAC[path_image; FORALL_IN_IMAGE] THEN X_GEN_TAC `x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN STRIP_TAC THEN REWRITE_TAC[IN_IMAGE; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `y:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN STRIP_TAC THEN SUBST1_TAC(SYM(ASSUME `(g1:real^1->real^N)(vec 1) = g2(vec 0:real^1)`)) THEN MATCH_MP_TAC(SET_RULE `x = a \/ x = b ==> f x IN {f a,f b}`) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`&1 / &2 % x:real^1`; `&1 / &2 % (y + vec 1):real^1`]) THEN ANTS_TAC THENL [REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_CMUL; DROP_ADD] THEN REPEAT(CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [joinpaths] THEN ASM_SIMP_TAC[JOINPATHS; pathstart; pathfinish] THEN REWRITE_TAC[DROP_ADD; DROP_CMUL; DROP_VEC] THEN REPEAT(COND_CASES_TAC THEN TRY ASM_REAL_ARITH_TAC) THEN REWRITE_TAC[VECTOR_ARITH `&2 % &1 / &2 % x:real^N = x`] THEN ASM_REWRITE_TAC[VECTOR_ARITH `(a + b) - b:real^N = a`]; REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_ADD; DROP_VEC] THEN ASM_REAL_ARITH_TAC]]);;
let SIMPLE_PATH_JOIN_LOOP_EQ = 
prove (`!g1 g2:real^1->real^N. pathfinish g2 = pathstart g1 /\ pathfinish g1 = pathstart g2 ==> (simple_path(g1 ++ g2) <=> arc g1 /\ arc g2 /\ path_image g1 INTER path_image g2 SUBSET {pathstart g1, pathstart g2})`,
let ARC_JOIN_EQ = 
prove (`!g1 g2:real^1->real^N. pathfinish g1 = pathstart g2 ==> (arc(g1 ++ g2) <=> arc g1 /\ arc g2 /\ path_image g1 INTER path_image g2 SUBSET {pathstart g2})`,
REPEAT STRIP_TAC THEN EQ_TAC THEN ASM_SIMP_TAC[ARC_JOIN] THEN GEN_REWRITE_TAC LAND_CONV [ARC_SIMPLE_PATH] THEN REWRITE_TAC[PATHFINISH_JOIN; PATHSTART_JOIN] THEN STRIP_TAC THEN MP_TAC(ISPECL [`g1:real^1->real^N`; `g2:real^1->real^N`] SIMPLE_PATH_JOIN_IMP) THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `~((pathstart g1:real^N) IN path_image g2)` (fun th -> MP_TAC th THEN ASM SET_TAC[]) THEN REWRITE_TAC[path_image; IN_IMAGE; IN_INTERVAL_1; DROP_VEC] THEN DISCH_THEN(X_CHOOSE_THEN `u:real^1` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [simple_path]) THEN DISCH_THEN(MP_TAC o SPECL [`vec 0:real^1`; `lift(&1 / &2) + inv(&2) % u`] o CONJUNCT2) THEN REWRITE_TAC[GSYM DROP_EQ; IN_INTERVAL_1; DROP_ADD; DROP_VEC; DROP_CMUL; LIFT_DROP; joinpaths] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM_SIMP_TAC[REAL_LT_IMP_LE; REAL_LT_IMP_NZ; REAL_ARITH `&0 <= x ==> &0 < &1 / &2 + &1 / &2 * x`] THEN REWRITE_TAC[REAL_ARITH `&1 / &2 + &1 / &2 * u = &1 <=> u = &1`] THEN ASM_SIMP_TAC[REAL_ARITH `&0 <= u ==> (&1 / &2 + &1 / &2 * u <= &1 / &2 <=> u = &0)`] THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish]) THEN ASM_REWRITE_TAC[VECTOR_MUL_RZERO] THEN ASM_SIMP_TAC[REAL_ARITH `u <= &1 ==> &1 / &2 + &1 / &2 * u <= &1`] THEN REWRITE_TAC[GSYM LIFT_EQ; LIFT_NUM; LIFT_DROP] THEN COND_CASES_TAC THENL [ASM_REWRITE_TAC[VECTOR_MUL_RZERO; VECTOR_ADD_RID; GSYM LIFT_CMUL] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LIFT_NUM] THEN ASM_REWRITE_TAC[VEC_EQ] THEN ARITH_TAC; REWRITE_TAC[VECTOR_ADD_LDISTRIB; GSYM LIFT_CMUL] THEN REWRITE_TAC[VECTOR_MUL_ASSOC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LIFT_NUM; VECTOR_MUL_LID; VECTOR_ADD_SUB] THEN ASM_MESON_TAC[]]);;
let ARC_JOIN_EQ_ALT = 
prove (`!g1 g2:real^1->real^N. pathfinish g1 = pathstart g2 ==> (arc(g1 ++ g2) <=> arc g1 /\ arc g2 /\ path_image g1 INTER path_image g2 = {pathstart g2})`,
REPEAT STRIP_TAC THEN ASM_SIMP_TAC[ARC_JOIN_EQ] THEN MP_TAC(ISPEC `g1:real^1->real^N` PATHFINISH_IN_PATH_IMAGE) THEN MP_TAC(ISPEC `g2:real^1->real^N` PATHSTART_IN_PATH_IMAGE) THEN ASM SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Reassociating a joined path doesn't matter for various properties. *) (* ------------------------------------------------------------------------- *)
let PATH_ASSOC = 
prove (`!p q r:real^1->real^N. pathfinish p = pathstart q /\ pathfinish q = pathstart r ==> (path(p ++ (q ++ r)) <=> path((p ++ q) ++ r))`,
SIMP_TAC[PATH_JOIN; PATHSTART_JOIN; PATHFINISH_JOIN] THEN CONV_TAC TAUT);;
let SIMPLE_PATH_ASSOC = 
prove (`!p q r:real^1->real^N. pathfinish p = pathstart q /\ pathfinish q = pathstart r ==> (simple_path(p ++ (q ++ r)) <=> simple_path((p ++ q) ++ r))`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `pathstart(p:real^1->real^N) = pathfinish r` THENL [ALL_TAC; ASM_SIMP_TAC[SIMPLE_PATH_EQ_ARC; PATHSTART_JOIN; PATHFINISH_JOIN]] THEN ASM_SIMP_TAC[SIMPLE_PATH_JOIN_LOOP_EQ; PATHSTART_JOIN; PATHFINISH_JOIN; ARC_JOIN_EQ; PATH_IMAGE_JOIN] THEN MAP_EVERY ASM_CASES_TAC [`arc(p:real^1->real^N)`; `arc(q:real^1->real^N)`; `arc(r:real^1->real^N)`] THEN ASM_REWRITE_TAC[UNION_OVER_INTER; UNION_SUBSET; ONCE_REWRITE_RULE[INTER_COMM] UNION_OVER_INTER] THEN REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP ARC_DISTINCT_ENDS)) THEN MAP_EVERY (fun t -> MP_TAC(ISPEC t PATHSTART_IN_PATH_IMAGE) THEN MP_TAC(ISPEC t PATHFINISH_IN_PATH_IMAGE)) [`p:real^1->real^N`; `q:real^1->real^N`; `r:real^1->real^N`] THEN ASM SET_TAC[]);;
let ARC_ASSOC = 
prove (`!p q r:real^1->real^N. pathfinish p = pathstart q /\ pathfinish q = pathstart r ==> (arc(p ++ (q ++ r)) <=> arc((p ++ q) ++ r))`,
(* ------------------------------------------------------------------------- *) (* In the case of a loop, neither does symmetry. *) (* ------------------------------------------------------------------------- *)
let PATH_SYM = 
prove (`!p q. pathfinish p = pathstart q /\ pathfinish q = pathstart p ==> (path(p ++ q) <=> path(q ++ p))`,
SIMP_TAC[PATH_JOIN; CONJ_ACI]);;
let SIMPLE_PATH_SYM = 
prove (`!p q. pathfinish p = pathstart q /\ pathfinish q = pathstart p ==> (simple_path(p ++ q) <=> simple_path(q ++ p))`,
let PATH_IMAGE_SYM = 
prove (`!p q. pathfinish p = pathstart q /\ pathfinish q = pathstart p ==> path_image(p ++ q) = path_image(q ++ p)`,
SIMP_TAC[PATH_IMAGE_JOIN; UNION_ACI]);;
(* ------------------------------------------------------------------------- *) (* Reparametrizing a closed curve to start at some chosen point. *) (* ------------------------------------------------------------------------- *)
let shiftpath = new_definition
  `shiftpath a (f:real^1->real^N) =
        \x. if drop(a + x) <= &1 then f(a + x)
            else f(a + x - vec 1)`;;
let SHIFTPATH_TRANSLATION = 
prove (`!a t g. shiftpath t ((\x. a + x) o g) = (\x. a + x) o shiftpath t g`,
REWRITE_TAC[FUN_EQ_THM; shiftpath; o_THM] THEN MESON_TAC[]);;
add_translation_invariants [SHIFTPATH_TRANSLATION];;
let SHIFTPATH_LINEAR_IMAGE = 
prove (`!f t g. linear f ==> shiftpath t (f o g) = f o shiftpath t g`,
REWRITE_TAC[FUN_EQ_THM; shiftpath; o_THM] THEN MESON_TAC[]);;
add_linear_invariants [SHIFTPATH_LINEAR_IMAGE];;
let PATHSTART_SHIFTPATH = 
prove (`!a g. drop a <= &1 ==> pathstart(shiftpath a g) = g(a)`,
let PATHFINISH_SHIFTPATH = 
prove (`!a g. &0 <= drop a /\ pathfinish g = pathstart g ==> pathfinish(shiftpath a g) = g(a)`,
SIMP_TAC[pathfinish; shiftpath; pathstart; DROP_ADD; DROP_VEC] THEN REWRITE_TAC[VECTOR_ARITH `a + vec 1 - vec 1 = a`] THEN ASM_SIMP_TAC[REAL_ARITH `&0 <= x ==> (x + &1 <= &1 <=> x = &0)`] THEN SIMP_TAC[DROP_EQ_0; VECTOR_ADD_LID] THEN MESON_TAC[]);;
let ENDPOINTS_SHIFTPATH = 
prove (`!a g. pathfinish g = pathstart g /\ a IN interval[vec 0,vec 1] ==> pathfinish(shiftpath a g) = g a /\ pathstart(shiftpath a g) = g a`,
let CLOSED_SHIFTPATH = 
prove (`!a g. pathfinish g = pathstart g /\ a IN interval[vec 0,vec 1] ==> pathfinish(shiftpath a g) = pathstart(shiftpath a g)`,
let PATH_SHIFTPATH = 
prove (`!g a. path g /\ pathfinish g:real^N = pathstart g /\ a IN interval[vec 0,vec 1] ==> path(shiftpath a g)`,
REWRITE_TAC[shiftpath; path] THEN REPEAT STRIP_TAC THEN SUBGOAL_THEN `interval[vec 0,vec 1] = interval[vec 0,vec 1 - a:real^1] UNION interval[vec 1 - a,vec 1]` SUBST1_TAC THENL [REWRITE_TAC[EXTENSION; IN_UNION; IN_INTERVAL_1] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN REWRITE_TAC[DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_UNION THEN REWRITE_TAC[CLOSED_INTERVAL] THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_EQ THENL [EXISTS_TAC `(\x. g(a + x)):real^1->real^N` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_ADD; DROP_VEC; DROP_SUB] THEN SIMP_TAC[REAL_ARITH `a + x <= &1 <=> x <= &1 - a`]; EXISTS_TAC `(\x. g(a + x - vec 1)):real^1->real^N` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_ADD; DROP_VEC; DROP_SUB] THEN SIMP_TAC[REAL_ARITH `&1 - a <= x ==> (a + x <= &1 <=> a + x = &1)`] THEN ONCE_REWRITE_TAC[COND_RAND] THEN REWRITE_TAC[VECTOR_ARITH `a + x - vec 1 = (a + x) - vec 1`] THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish]) THEN ASM_SIMP_TAC[GSYM LIFT_EQ; LIFT_ADD; LIFT_NUM; LIFT_DROP] THEN REWRITE_TAC[VECTOR_SUB_REFL; COND_ID]] THEN MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_COMPOSE) THEN SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID; CONTINUOUS_ON_SUB] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_SUB; DROP_VEC; DROP_ADD] THEN REAL_ARITH_TAC);;
let SHIFTPATH_SHIFTPATH = 
prove (`!g a x. a IN interval[vec 0,vec 1] /\ pathfinish g = pathstart g /\ x IN interval[vec 0,vec 1] ==> shiftpath (vec 1 - a) (shiftpath a g) x = g x`,
REWRITE_TAC[shiftpath; pathfinish; pathstart] THEN REWRITE_TAC[DROP_ADD; DROP_SUB; DROP_VEC] THEN REPEAT STRIP_TAC THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN REWRITE_TAC[DROP_VEC] THEN REPEAT STRIP_TAC THENL [ALL_TAC; AP_TERM_TAC THEN VECTOR_ARITH_TAC; AP_TERM_TAC THEN VECTOR_ARITH_TAC; ASM_REAL_ARITH_TAC] THEN SUBGOAL_THEN `x:real^1 = vec 0` SUBST1_TAC THENL [REWRITE_TAC[GSYM DROP_EQ; DROP_VEC] THEN ASM_REAL_ARITH_TAC; ASM_REWRITE_TAC[VECTOR_ARITH `a + vec 1 - a + vec 0:real^1 = vec 1`]]);;
let PATH_IMAGE_SHIFTPATH = 
prove (`!a g:real^1->real^N. a IN interval[vec 0,vec 1] /\ pathfinish g = pathstart g ==> path_image(shiftpath a g) = path_image g`,
REWRITE_TAC[IN_INTERVAL_1; pathfinish; pathstart] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THEN REWRITE_TAC[path_image; shiftpath; FORALL_IN_IMAGE; SUBSET] THEN REWRITE_TAC[IN_IMAGE] THEN REPEAT STRIP_TAC THEN REPEAT COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_IMAGE] THENL [EXISTS_TAC `a + x:real^1`; EXISTS_TAC `a + x - vec 1:real^1`; ALL_TAC] THEN REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; DROP_SUB; DROP_ADD] THEN TRY REAL_ARITH_TAC THEN REPEAT STRIP_TAC THEN ASM_CASES_TAC `drop a <= drop x` THENL [EXISTS_TAC `x - a:real^1` THEN REWRITE_TAC[VECTOR_ARITH `a + x - a:real^1 = x`; DROP_SUB] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC; EXISTS_TAC `vec 1 + x - a:real^1` THEN REWRITE_TAC[VECTOR_ARITH `a + (v + x - a) - v:real^1 = x`] THEN REWRITE_TAC[DROP_ADD; DROP_SUB; DROP_VEC] THEN ASM_CASES_TAC `x:real^1 = vec 0` THEN ASM_REWRITE_TAC[VECTOR_ARITH `a + v + x - a:real^1 = v + x`] THEN ASM_REWRITE_TAC[VECTOR_ADD_RID; DROP_VEC; COND_ID] THEN ASM_REWRITE_TAC[REAL_ARITH `a + &1 + x - a <= &1 <=> x <= &0`] THEN REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[GSYM DROP_EQ; DROP_VEC] THEN TRY(COND_CASES_TAC THEN POP_ASSUM MP_TAC) THEN REWRITE_TAC[] THEN REAL_ARITH_TAC]);;
let SIMPLE_PATH_SHIFTPATH = 
prove (`!g a. simple_path g /\ pathfinish g = pathstart g /\ a IN interval[vec 0,vec 1] ==> simple_path(shiftpath a g)`,
REPEAT GEN_TAC THEN REWRITE_TAC[simple_path] THEN MATCH_MP_TAC(TAUT `(a /\ c /\ d ==> e) /\ (b /\ c /\ d ==> f) ==> (a /\ b) /\ c /\ d ==> e /\ f`) THEN CONJ_TAC THENL [MESON_TAC[PATH_SHIFTPATH]; ALL_TAC] THEN REWRITE_TAC[simple_path; shiftpath; IN_INTERVAL_1; DROP_VEC; DROP_ADD; DROP_SUB] THEN REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> c ==> a /\ b ==> d`] THEN STRIP_TAC THEN REPEAT GEN_TAC THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN DISCH_THEN(fun th -> FIRST_X_ASSUM(MP_TAC o C MATCH_MP th)) THEN REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[DROP_ADD; DROP_SUB; DROP_VEC; GSYM DROP_EQ] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Choosing a sub-path of an existing path. *) (* ------------------------------------------------------------------------- *)
let subpath = new_definition
 `subpath u v g = \x. g(u + drop(v - u) % x)`;;
let SUBPATH_SCALING_LEMMA = 
prove (`!u v. IMAGE (\x. u + drop(v - u) % x) (interval[vec 0,vec 1]) = segment[u,v]`,
REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[VECTOR_ADD_SYM] THEN REWRITE_TAC[IMAGE_AFFINITY_INTERVAL; SEGMENT_1] THEN REWRITE_TAC[DROP_SUB; REAL_SUB_LE; INTERVAL_EQ_EMPTY_1; DROP_VEC] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN BINOP_TAC THEN REWRITE_TAC[GSYM LIFT_EQ_CMUL; VECTOR_MUL_RZERO] THEN REWRITE_TAC[LIFT_DROP; LIFT_SUB] THEN VECTOR_ARITH_TAC);;
let PATH_IMAGE_SUBPATH_GEN = 
prove (`!u v g:real^1->real^N. path_image(subpath u v g) = IMAGE g (segment[u,v])`,
REPEAT GEN_TAC THEN REWRITE_TAC[path_image; subpath] THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o; SUBPATH_SCALING_LEMMA]);;
let PATH_IMAGE_SUBPATH = 
prove (`!u v g:real^1->real^N. drop u <= drop v ==> path_image(subpath u v g) = IMAGE g (interval[u,v])`,
let PATH_SUBPATH = 
prove (`!u v g:real^1->real^N. path g /\ u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] ==> path(subpath u v g)`,
REWRITE_TAC[path; subpath] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_COMPOSE) THEN SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] CONTINUOUS_ON_SUBSET)) THEN REWRITE_TAC[SUBPATH_SCALING_LEMMA; SEGMENT_1] THEN COND_CASES_TAC THEN REWRITE_TAC[SUBSET_INTERVAL_1] THEN REPEAT(POP_ASSUM MP_TAC) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN REAL_ARITH_TAC);;
let PATHSTART_SUBPATH = 
prove (`!u v g:real^1->real^N. pathstart(subpath u v g) = g(u)`,
let PATHFINISH_SUBPATH = 
prove (`!u v g:real^1->real^N. pathfinish(subpath u v g) = g(v)`,
REWRITE_TAC[pathfinish; subpath; GSYM LIFT_EQ_CMUL] THEN REWRITE_TAC[LIFT_DROP; VECTOR_ARITH `u + v - u:real^N = v`]);;
let SUBPATH_TRIVIAL = 
prove (`!g. subpath (vec 0) (vec 1) g = g`,
let SUBPATH_REVERSEPATH = 
prove (`!g. subpath (vec 1) (vec 0) g = reversepath g`,
REWRITE_TAC[subpath; reversepath; VECTOR_SUB_LZERO; DROP_NEG; DROP_VEC] THEN REWRITE_TAC[VECTOR_ARITH `a + -- &1 % b:real^N = a - b`]);;
let REVERSEPATH_SUBPATH = 
prove (`!g u v. reversepath(subpath u v g) = subpath v u g`,
REWRITE_TAC[reversepath; subpath; FUN_EQ_THM] THEN REPEAT GEN_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[DROP_SUB; VECTOR_SUB_LDISTRIB] THEN REWRITE_TAC[GSYM LIFT_EQ_CMUL; LIFT_SUB; LIFT_DROP] THEN VECTOR_ARITH_TAC);;
let SUBPATH_TRANSLATION = 
prove (`!a g u v. subpath u v ((\x. a + x) o g) = (\x. a + x) o subpath u v g`,
REWRITE_TAC[FUN_EQ_THM; subpath; o_THM]);;
add_translation_invariants [SUBPATH_TRANSLATION];;
let SUBPATH_LINEAR_IMAGE = 
prove (`!f g u v. linear f ==> subpath u v (f o g) = f o subpath u v g`,
REWRITE_TAC[FUN_EQ_THM; subpath; o_THM]);;
add_linear_invariants [SUBPATH_LINEAR_IMAGE];;
let SIMPLE_PATH_SUBPATH_EQ = 
prove (`!g u v. simple_path(subpath u v g) <=> path(subpath u v g) /\ ~(u = v) /\ (!x y. x IN segment[u,v] /\ y IN segment[u,v] /\ g x = g y ==> x = y \/ x = u /\ y = v \/ x = v /\ y = u)`,
REPEAT GEN_TAC THEN REWRITE_TAC[simple_path; subpath] THEN AP_TERM_TAC THEN REWRITE_TAC[GSYM SUBPATH_SCALING_LEMMA] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[VECTOR_ARITH `u + a % x = u <=> a % x = vec 0`; VECTOR_ARITH `a + x:real^N = a + y <=> x = y`] THEN REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_MUL_LCANCEL] THEN REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_ADD; DROP_SUB; REAL_RING `u + (v - u) * y = v <=> v = u \/ y = &1`] THEN REWRITE_TAC[REAL_SUB_0; DROP_EQ; GSYM DROP_VEC] THEN ASM_CASES_TAC `v:real^1 = u` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[REAL_SUB_REFL; DROP_VEC; VECTOR_MUL_LZERO] THEN REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN DISCH_THEN(MP_TAC o SPECL [`lift(&1 / &2)`; `lift(&3 / &4)`]) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; GSYM DROP_EQ; LIFT_DROP] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let ARC_SUBPATH_EQ = 
prove (`!g u v. arc(subpath u v g) <=> path(subpath u v g) /\ ~(u = v) /\ (!x y. x IN segment[u,v] /\ y IN segment[u,v] /\ g x = g y ==> x = y)`,
REPEAT GEN_TAC THEN REWRITE_TAC[arc; subpath] THEN AP_TERM_TAC THEN REWRITE_TAC[GSYM SUBPATH_SCALING_LEMMA] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REWRITE_TAC[VECTOR_ARITH `u + a % x = u + a % y <=> a % (x - y) = vec 0`; VECTOR_MUL_EQ_0; DROP_EQ_0; VECTOR_SUB_EQ] THEN ASM_CASES_TAC `v:real^1 = u` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[VECTOR_SUB_REFL; DROP_VEC; VECTOR_MUL_LZERO] THEN REWRITE_TAC[RIGHT_IMP_FORALL_THM] THEN DISCH_THEN(MP_TAC o SPECL [`lift(&1 / &2)`; `lift(&3 / &4)`]) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; GSYM DROP_EQ; LIFT_DROP] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let SIMPLE_PATH_SUBPATH = 
prove (`!g u v. simple_path g /\ u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\ ~(u = v) ==> simple_path(subpath u v g)`,
SIMP_TAC[SIMPLE_PATH_SUBPATH_EQ; PATH_SUBPATH; SIMPLE_PATH_IMP_PATH] THEN REWRITE_TAC[simple_path] THEN GEN_TAC THEN REWRITE_TAC[FORALL_LIFT] THEN MATCH_MP_TAC REAL_WLOG_LT THEN REWRITE_TAC[FORALL_DROP; LIFT_DROP] THEN CONJ_TAC THENL [MESON_TAC[SEGMENT_SYM]; ALL_TAC] THEN SIMP_TAC[SEGMENT_1; REAL_LT_IMP_LE] THEN MAP_EVERY X_GEN_TAC [`u:real^1`; `v:real^1`] THEN DISCH_TAC THEN STRIP_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^1`; `y:real^1`]) THEN SUBGOAL_THEN `!x:real^1. x IN interval[u,v] ==> x IN interval[vec 0,vec 1]` ASSUME_TAC THENL [REWRITE_TAC[GSYM SUBSET; SUBSET_INTERVAL_1] THEN ASM_MESON_TAC[IN_INTERVAL_1; DROP_VEC; REAL_LE_TRANS]; ASM_SIMP_TAC[]] THEN REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN REWRITE_TAC[DROP_VEC; GSYM DROP_EQ] THEN ASM_REAL_ARITH_TAC);;
let ARC_SIMPLE_PATH_SUBPATH = 
prove (`!g u v. simple_path g /\ u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\ ~(g u = g v) ==> arc(subpath u v g)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SIMPLE_PATH_IMP_ARC THEN ASM_REWRITE_TAC[PATHSTART_SUBPATH; PATHFINISH_SUBPATH] THEN ASM_MESON_TAC[SIMPLE_PATH_SUBPATH]);;
let ARC_SUBPATH_ARC = 
prove (`!u v g. arc g /\ u IN interval [vec 0,vec 1] /\ v IN interval [vec 0,vec 1] /\ ~(u = v) ==> arc(subpath u v g)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC ARC_SIMPLE_PATH_SUBPATH THEN ASM_MESON_TAC[ARC_IMP_SIMPLE_PATH; arc]);;
let ARC_SIMPLE_PATH_SUBPATH_INTERIOR = 
prove (`!g u v. simple_path g /\ u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\ ~(u = v) /\ abs(drop u - drop v) < &1 ==> arc(subpath u v g)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC ARC_SIMPLE_PATH_SUBPATH THEN ASM_REWRITE_TAC[] THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [simple_path]) THEN DISCH_THEN(MP_TAC o SPECL [`u:real^1`; `v:real^1`] o CONJUNCT2) THEN ASM_REWRITE_TAC[] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[DROP_VEC] THEN REAL_ARITH_TAC);;
let PATH_IMAGE_SUBPATH_SUBSET = 
prove (`!u v g:real^1->real^N. path g /\ u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] ==> path_image(subpath u v g) SUBSET path_image g`,
SIMP_TAC[PATH_IMAGE_SUBPATH_GEN] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[path_image] THEN MATCH_MP_TAC IMAGE_SUBSET THEN SIMP_TAC[SEGMENT_CONVEX_HULL; SUBSET_HULL; CONVEX_INTERVAL] THEN ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET]);;
let JOIN_SUBPATHS_MIDDLE = 
prove (`!p:real^1->real^N. subpath (vec 0) (lift(&1 / &2)) p ++ subpath (lift(&1 / &2)) (vec 1) p = p`,
REWRITE_TAC[FUN_EQ_THM] THEN REPEAT GEN_TAC THEN REWRITE_TAC[joinpaths; subpath] THEN COND_CASES_TAC THEN AP_TERM_TAC THEN REWRITE_TAC[GSYM DROP_EQ; DROP_ADD; DROP_SUB; DROP_CMUL; LIFT_DROP; DROP_VEC] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Some additional lemmas about choosing sub-paths. *) (* ------------------------------------------------------------------------- *)
let EXISTS_SUBPATH_OF_PATH = 
prove (`!g a b:real^N. path g /\ a IN path_image g /\ b IN path_image g ==> ?h. path h /\ pathstart h = a /\ pathfinish h = b /\ path_image h SUBSET path_image g`,
REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; path_image; FORALL_IN_IMAGE] THEN GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `u:real^1` THEN DISCH_TAC THEN X_GEN_TAC `v:real^1` THEN DISCH_TAC THEN EXISTS_TAC `subpath u v (g:real^1->real^N)` THEN ASM_REWRITE_TAC[GSYM path_image; PATH_IMAGE_SUBPATH_GEN] THEN ASM_SIMP_TAC[PATH_SUBPATH; PATHSTART_SUBPATH; PATHFINISH_SUBPATH] THEN REWRITE_TAC[path_image] THEN MATCH_MP_TAC IMAGE_SUBSET THEN SIMP_TAC[SEGMENT_CONVEX_HULL; SUBSET_HULL; CONVEX_INTERVAL] THEN ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET]);;
let EXISTS_SUBPATH_OF_ARC_NOENDS = 
prove (`!g a b:real^N. arc g /\ a IN path_image g /\ b IN path_image g /\ {a,b} INTER {pathstart g,pathfinish g} = {} ==> ?h. path h /\ pathstart h = a /\ pathfinish h = b /\ path_image h SUBSET (path_image g) DIFF {pathstart g,pathfinish g}`,
REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; path_image; FORALL_IN_IMAGE] THEN GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `u:real^1` THEN DISCH_TAC THEN X_GEN_TAC `v:real^1` THEN DISCH_TAC THEN DISCH_TAC THEN EXISTS_TAC `subpath u v (g:real^1->real^N)` THEN ASM_SIMP_TAC[PATH_SUBPATH; PATHSTART_SUBPATH; PATHFINISH_SUBPATH; ARC_IMP_PATH; GSYM path_image; PATH_IMAGE_SUBPATH_GEN] THEN REWRITE_TAC[path_image; pathstart; pathfinish] THEN REWRITE_TAC[SET_RULE `s SUBSET t DIFF {a,b} <=> s SUBSET t /\ ~(a IN s) /\ ~(b IN s)`] THEN REWRITE_TAC[IN_IMAGE] THEN SUBGOAL_THEN `~(vec 0 IN segment[u:real^1,v]) /\ ~(vec 1 IN segment[u,v])` STRIP_ASSUME_TAC THENL [REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN REWRITE_TAC[SEGMENT_1] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN SIMP_TAC[REAL_ARITH `a <= b ==> (b <= a <=> a = b)`] THEN REWRITE_TAC[GSYM DROP_VEC; DROP_EQ] THEN RULE_ASSUM_TAC(REWRITE_RULE[arc; pathstart; pathfinish]) THEN ASM SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `segment[u:real^1,v] SUBSET interval[vec 0,vec 1]` MP_TAC THENL [SIMP_TAC[SEGMENT_CONVEX_HULL; SUBSET_HULL; CONVEX_INTERVAL] THEN ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET]; ALL_TAC] THEN RULE_ASSUM_TAC(REWRITE_RULE[arc; pathstart; pathfinish]) THEN SUBGOAL_THEN `(vec 0:real^1) IN interval[vec 0,vec 1] /\ (vec 1:real^1) IN interval[vec 0,vec 1]` MP_TAC THENL [REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS; REAL_LE_REFL]; ASM SET_TAC[]]);;
let EXISTS_SUBARC_OF_ARC_NOENDS = 
prove (`!g a b:real^N. arc g /\ a IN path_image g /\ b IN path_image g /\ ~(a = b) /\ {a,b} INTER {pathstart g,pathfinish g} = {} ==> ?h. arc h /\ pathstart h = a /\ pathfinish h = b /\ path_image h SUBSET (path_image g) DIFF {pathstart g,pathfinish g}`,
REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; path_image; FORALL_IN_IMAGE] THEN GEN_TAC THEN DISCH_TAC THEN X_GEN_TAC `u:real^1` THEN DISCH_TAC THEN X_GEN_TAC `v:real^1` THEN REPEAT DISCH_TAC THEN EXISTS_TAC `subpath u v (g:real^1->real^N)` THEN ASM_SIMP_TAC[PATH_SUBPATH; PATHSTART_SUBPATH; PATHFINISH_SUBPATH; ARC_IMP_PATH; GSYM path_image; PATH_IMAGE_SUBPATH_GEN] THEN CONJ_TAC THENL [MATCH_MP_TAC ARC_SIMPLE_PATH_SUBPATH THEN ASM_SIMP_TAC[ARC_IMP_SIMPLE_PATH]; ALL_TAC] THEN REWRITE_TAC[path_image; pathstart; pathfinish] THEN REWRITE_TAC[SET_RULE `s SUBSET t DIFF {a,b} <=> s SUBSET t /\ ~(a IN s) /\ ~(b IN s)`] THEN REWRITE_TAC[IN_IMAGE] THEN SUBGOAL_THEN `~(vec 0 IN segment[u:real^1,v]) /\ ~(vec 1 IN segment[u,v])` STRIP_ASSUME_TAC THENL [REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN REWRITE_TAC[SEGMENT_1] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN SIMP_TAC[REAL_ARITH `a <= b ==> (b <= a <=> a = b)`] THEN REWRITE_TAC[GSYM DROP_VEC; DROP_EQ] THEN RULE_ASSUM_TAC(REWRITE_RULE[arc; pathstart; pathfinish]) THEN ASM SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `segment[u:real^1,v] SUBSET interval[vec 0,vec 1]` MP_TAC THENL [SIMP_TAC[SEGMENT_CONVEX_HULL; SUBSET_HULL; CONVEX_INTERVAL] THEN ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET]; ALL_TAC] THEN RULE_ASSUM_TAC(REWRITE_RULE[arc; pathstart; pathfinish]) THEN SUBGOAL_THEN `(vec 0:real^1) IN interval[vec 0,vec 1] /\ (vec 1:real^1) IN interval[vec 0,vec 1]` MP_TAC THENL [REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS; REAL_LE_REFL]; ASM SET_TAC[]]);;
let EXISTS_ARC_PSUBSET_SIMPLE_PATH = 
prove (`!g:real^1->real^N. simple_path g /\ closed s /\ s PSUBSET path_image g ==> ?h. arc h /\ s SUBSET path_image h /\ path_image h SUBSET path_image g`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(DISJ_CASES_TAC o MATCH_MP SIMPLE_PATH_CASES) THENL [EXISTS_TAC `g:real^1->real^N` THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]; ALL_TAC] THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [PSUBSET_ALT]) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [path_image] THEN REWRITE_TAC[EXISTS_IN_IMAGE] THEN DISCH_THEN(X_CHOOSE_THEN `u:real^1` STRIP_ASSUME_TAC) THEN ABBREV_TAC `(h:real^1->real^N) = shiftpath u g` THEN SUBGOAL_THEN `simple_path(h:real^1->real^N) /\ pathstart h = (g:real^1->real^N) u /\ pathfinish h = (g:real^1->real^N) u /\ path_image h = path_image g` MP_TAC THENL [EXPAND_TAC "h" THEN ASM_MESON_TAC[SIMPLE_PATH_SHIFTPATH; PATH_IMAGE_SHIFTPATH; PATHSTART_SHIFTPATH; PATHFINISH_SHIFTPATH; IN_INTERVAL_1; DROP_VEC]; REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN DISCH_THEN(SUBST_ALL_TAC o SYM) THEN UNDISCH_THEN `pathstart(h:real^1->real^N) = (g:real^1->real^N) u` (SUBST_ALL_TAC o SYM)] THEN SUBGOAL_THEN `open_in (subtopology euclidean (interval[vec 0,vec 1])) {x:real^1 | x IN interval[vec 0,vec 1] /\ (h x) IN ((:real^N) DIFF s)}` MP_TAC THENL [MATCH_MP_TAC CONTINUOUS_OPEN_IN_PREIMAGE THEN ASM_SIMP_TAC[GSYM path; GSYM closed; SIMPLE_PATH_IMP_PATH]; REWRITE_TAC[open_in] THEN DISCH_THEN(MP_TAC o CONJUNCT2)] THEN REWRITE_TAC[IN_DIFF; IN_UNIV; IN_ELIM_THM] THEN DISCH_THEN(fun th -> MP_TAC(SPEC `vec 0:real^1` th) THEN MP_TAC(SPEC `vec 1:real^1` th)) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS; REAL_LE_REFL] THEN REWRITE_TAC[DIST_REAL; VEC_COMPONENT; REAL_SUB_RZERO] THEN SIMP_TAC[GSYM drop] THEN ANTS_TAC THENL [ASM_MESON_TAC[pathfinish]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `d2:real` STRIP_ASSUME_TAC) THEN ANTS_TAC THENL [ASM_MESON_TAC[pathstart]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `d1:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `subpath (lift(min d1 (&1 / &4))) (lift(&1 - min d2 (&1 / &4))) (h:real^1->real^N)` THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC ARC_SIMPLE_PATH_SUBPATH_INTERIOR THEN ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; LIFT_DROP; LIFT_EQ] THEN ASM_REAL_ARITH_TAC; FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `s SUBSET t ==> t INTER s SUBSET u ==> s SUBSET u`)) THEN REWRITE_TAC[SUBSET; IN_INTER; IMP_CONJ] THEN SIMP_TAC[PATH_IMAGE_SUBPATH; LIFT_DROP; REAL_ARITH `min d1 (&1 / &4) <= &1 - min d2 (&1 / &4)`] THEN REWRITE_TAC[FORALL_IN_IMAGE; path_image; IN_INTERVAL_1; DROP_VEC] THEN X_GEN_TAC `x:real^1` THEN REPEAT STRIP_TAC THEN REWRITE_TAC[IN_IMAGE] THEN EXISTS_TAC `x:real^1` THEN ASM_REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP] THEN REPEAT(FIRST_X_ASSUM(MP_TAC o SPEC `x:real^1`)) THEN ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC; MATCH_MP_TAC PATH_IMAGE_SUBPATH_SUBSET THEN ASM_SIMP_TAC[SIMPLE_PATH_IMP_PATH; IN_INTERVAL_1; LIFT_DROP; DROP_VEC] THEN ASM_REAL_ARITH_TAC]);;
let EXISTS_DOUBLE_ARC = 
prove (`!g:real^1->real^N a b. simple_path g /\ pathfinish g = pathstart g /\ a IN path_image g /\ b IN path_image g /\ ~(a = b) ==> ?u d. arc u /\ arc d /\ pathstart u = a /\ pathfinish u = b /\ pathstart d = b /\ pathfinish d = a /\ (path_image u) INTER (path_image d) = {a,b} /\ (path_image u) UNION (path_image d) = path_image g`,
REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; path_image] THEN ONCE_REWRITE_TAC[FORALL_IN_IMAGE] THEN GEN_TAC THEN REPEAT DISCH_TAC THEN X_GEN_TAC `u:real^1` THEN DISCH_TAC THEN REWRITE_TAC[GSYM path_image] THEN X_GEN_TAC `b:real^N` THEN DISCH_TAC THEN DISCH_TAC THEN ABBREV_TAC `h = shiftpath u (g:real^1->real^N)` THEN SUBGOAL_THEN `simple_path(h:real^1->real^N) /\ pathstart h = g u /\ pathfinish h = g u /\ path_image h = path_image g` STRIP_ASSUME_TAC THENL [EXPAND_TAC "h" THEN ASM_SIMP_TAC[SIMPLE_PATH_SHIFTPATH; PATH_IMAGE_SHIFTPATH] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1; DROP_VEC]) THEN EXPAND_TAC "h" THEN ASM_SIMP_TAC[PATHSTART_SHIFTPATH; PATHFINISH_SHIFTPATH]; UNDISCH_THEN `path_image h :real^N->bool = path_image g` (SUBST_ALL_TAC o SYM)] THEN UNDISCH_TAC `(b:real^N) IN path_image h` THEN REWRITE_TAC[IN_IMAGE; path_image; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `v:real^1` THEN STRIP_TAC THEN REWRITE_TAC[GSYM path_image] THEN MAP_EVERY EXISTS_TAC [`subpath (vec 0) v (h:real^1->real^N)`; `subpath v (vec 1) (h:real^1->real^N)`] THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish]) THEN ASM_REWRITE_TAC[PATHSTART_SUBPATH; PATHFINISH_SUBPATH] THEN UNDISCH_THEN `b = (h:real^1->real^N) v` SUBST_ALL_TAC THEN STRIP_ASSUME_TAC(REWRITE_RULE[IN_INTERVAL_1; DROP_VEC] (ASSUME `(v:real^1) IN interval[vec 0,vec 1]`)) THEN ASM_SIMP_TAC[ARC_SIMPLE_PATH_SUBPATH; IN_INTERVAL_1; DROP_VEC; REAL_LE_REFL; REAL_POS; PATH_IMAGE_SUBPATH] THEN REWRITE_TAC[GSYM IMAGE_UNION; path_image] THEN UNDISCH_THEN `(h:real^1->real^N)(vec 0) = (g:real^1->real^N) u` (SUBST_ALL_TAC o SYM) THEN SUBGOAL_THEN `interval[vec 0,v] UNION interval[v,vec 1] = interval[vec 0:real^1,vec 1]` ASSUME_TAC THENL [ALL_TAC; ASM_SIMP_TAC[IMAGE_SUBSET] THEN MATCH_MP_TAC(SET_RULE `(!x y. x IN (s UNION t) /\ y IN (s UNION t) /\ f x = f y ==> x = y \/ x = vec 0 /\ y = vec 1 \/ x = vec 1 /\ y = vec 0) /\ (f(vec 0) = f(vec 1)) /\ (vec 0) IN s /\ (vec 1) IN t /\ s INTER t = {c} ==> IMAGE f s INTER IMAGE f t = {f (vec 0), f c}`) THEN RULE_ASSUM_TAC(REWRITE_RULE[simple_path]) THEN ASM_REWRITE_TAC[]] THEN REWRITE_TAC[EXTENSION; IN_INSERT; NOT_IN_EMPTY; IN_INTER; IN_UNION] THEN REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1])) THEN REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ; DROP_VEC] THEN ASM_REAL_ARITH_TAC);;
let SUBPATH_TO_FRONTIER_EXPLICIT = 
prove (`!g:real^1->real^N s. path g /\ pathstart g IN s /\ ~(pathfinish g IN s) ==> ?u. u IN interval[vec 0,vec 1] /\ (!x. &0 <= drop x /\ drop x < drop u ==> g x IN interior s) /\ ~(g u IN interior s) /\ (u = vec 0 \/ g u IN closure s)`,
REPEAT STRIP_TAC THEN MP_TAC(ISPEC `{u | lift u IN interval[vec 0,vec 1] /\ g(lift u) IN closure((:real^N) DIFF s)}` COMPACT_ATTAINS_INF) THEN SIMP_TAC[LIFT_DROP; SET_RULE `(!x. lift(drop x) = x) ==> IMAGE lift {x | P(lift x)} = {x | P x}`] THEN ANTS_TAC THENL [RULE_ASSUM_TAC(REWRITE_RULE[path; pathstart; pathfinish; SUBSET; path_image; FORALL_IN_IMAGE]) THEN CONJ_TAC THENL [REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN CONJ_TAC THENL [MATCH_MP_TAC BOUNDED_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN REWRITE_TAC[BOUNDED_INTERVAL] THEN SET_TAC[]; MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN ASM_REWRITE_TAC[CLOSED_CLOSURE; CLOSED_INTERVAL]]; REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_ELIM_THM] THEN EXISTS_TAC `&1` THEN REWRITE_TAC[LIFT_NUM] THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_POS; REAL_LE_REFL] THEN MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN ASM_REWRITE_TAC[IN_DIFF; IN_UNIV]]; ALL_TAC] THEN REWRITE_TAC[EXISTS_DROP; FORALL_DROP; IN_ELIM_THM; LIFT_DROP] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^1` THEN REWRITE_TAC[CLOSURE_COMPLEMENT; IN_DIFF; IN_UNIV] THEN STRIP_TAC THEN ASM_REWRITE_TAC[subpath; VECTOR_SUB_RZERO; VECTOR_ADD_LID] THEN ASM_REWRITE_TAC[GSYM LIFT_EQ_CMUL; LIFT_DROP] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1; DROP_VEC]) THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; GSYM DROP_EQ] THEN MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL [REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE BINDER_CONV [TAUT `a /\ ~b ==> c <=> a /\ ~c ==> b`]) THEN ASM_REAL_ARITH_TAC; FIRST_X_ASSUM(K ALL_TAC o SPEC `x:real^1`) THEN DISCH_TAC] THEN ASM_CASES_TAC `drop u = &0` THEN ASM_REWRITE_TAC[frontier; IN_DIFF; CLOSURE_APPROACHABLE] THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[path; pathstart; pathfinish]) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [continuous_on]) THEN DISCH_THEN(MP_TAC o SPEC `u:real^1`) THEN ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN DISCH_THEN(MP_TAC o SPEC `lift(max (&0) (drop u - d / &2))`) THEN REWRITE_TAC[LIFT_DROP; DIST_REAL; GSYM drop] THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC (MESON[] `P a ==> dist(a,y) < e ==> ?x. P x /\ dist(x,y) < e`) THEN MATCH_MP_TAC(REWRITE_RULE[SUBSET] INTERIOR_SUBSET) THEN FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[LIFT_DROP] THEN ASM_ARITH_TAC);;
let SUBPATH_TO_FRONTIER_STRONG = 
prove (`!g:real^1->real^N s. path g /\ pathstart g IN s /\ ~(pathfinish g IN s) ==> ?u. u IN interval[vec 0,vec 1] /\ ~(pathfinish(subpath (vec 0) u g) IN interior s) /\ (u = vec 0 \/ (!x. x IN interval[vec 0,vec 1] /\ ~(x = vec 1) ==> (subpath (vec 0) u g x) IN interior s) /\ pathfinish(subpath (vec 0) u g) IN closure s)`,
REPEAT GEN_TAC THEN DISCH_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP SUBPATH_TO_FRONTIER_EXPLICIT) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^1` THEN REWRITE_TAC[subpath; pathfinish; VECTOR_SUB_RZERO; VECTOR_ADD_LID] THEN ASM_CASES_TAC `u:real^1 = vec 0` THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[DROP_VEC; VECTOR_MUL_LZERO] THEN ASM_REWRITE_TAC[GSYM LIFT_EQ_CMUL; LIFT_DROP] THEN X_GEN_TAC `x:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ; DROP_VEC] THEN STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1; DROP_VEC]) THEN ASM_SIMP_TAC[DROP_CMUL; REAL_LE_MUL] THEN REWRITE_TAC[REAL_ARITH `u * x < u <=> &0 < u * (&1 - x)`] THEN MATCH_MP_TAC REAL_LT_MUL THEN REWRITE_TAC[REAL_SUB_LT] THEN ASM_REWRITE_TAC[REAL_LT_LE] THEN ASM_REWRITE_TAC[GSYM LIFT_EQ; LIFT_DROP; LIFT_NUM]);;
let SUBPATH_TO_FRONTIER = 
prove (`!g:real^1->real^N s. path g /\ pathstart g IN s /\ ~(pathfinish g IN s) ==> ?u. u IN interval[vec 0,vec 1] /\ pathfinish(subpath (vec 0) u g) IN frontier s /\ (path_image(subpath (vec 0) u g) DELETE pathfinish(subpath (vec 0) u g)) SUBSET interior s`,
REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[frontier; IN_DIFF] THEN FIRST_ASSUM(MP_TAC o MATCH_MP SUBPATH_TO_FRONTIER_STRONG) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^1` THEN ASM_CASES_TAC `u:real^1 = vec 0` THEN ASM_REWRITE_TAC[] THENL [REWRITE_TAC[PATHSTART_SUBPATH; PATHFINISH_SUBPATH] THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart]) THEN STRIP_TAC THEN ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN REWRITE_TAC[subpath; path_image; VECTOR_SUB_REFL; DROP_VEC; VECTOR_MUL_LZERO; VECTOR_ADD_LID] THEN SET_TAC[]; STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET; path_image; FORALL_IN_IMAGE; IN_DELETE; IMP_CONJ] THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; pathfinish] THEN REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN ASM_MESON_TAC[]]);;
let EXISTS_PATH_SUBPATH_TO_FRONTIER = 
prove (`!g:real^1->real^N s. path g /\ pathstart g IN s /\ ~(pathfinish g IN s) ==> ?h. path h /\ pathstart h = pathstart g /\ (path_image h) SUBSET (path_image g) /\ (path_image h DELETE (pathfinish h)) SUBSET interior s /\ pathfinish h IN frontier s`,
REPEAT GEN_TAC THEN DISCH_TAC THEN FIRST_ASSUM(STRIP_ASSUME_TAC o MATCH_MP SUBPATH_TO_FRONTIER) THEN EXISTS_TAC `subpath (vec 0) u (g:real^1->real^N)` THEN ASM_SIMP_TAC[PATH_SUBPATH; IN_INTERVAL_1; DROP_VEC; REAL_POS; REAL_LE_REFL; PATHSTART_SUBPATH; PATH_IMAGE_SUBPATH_SUBSET] THEN REWRITE_TAC[pathstart]);;
let EXISTS_PATH_SUBPATH_TO_FRONTIER_CLOSED = 
prove (`!g:real^1->real^N s. closed s /\ path g /\ pathstart g IN s /\ ~(pathfinish g IN s) ==> ?h. path h /\ pathstart h = pathstart g /\ (path_image h) SUBSET (path_image g) INTER s /\ pathfinish h IN frontier s`,
REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN ASSUME_TAC) THEN FIRST_ASSUM(MP_TAC o MATCH_MP EXISTS_PATH_SUBPATH_TO_FRONTIER) THEN MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[SUBSET_INTER] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `(pathfinish h:real^N) INSERT (path_image h DELETE pathfinish h)` THEN CONJ_TAC THENL [SET_TAC[]; REWRITE_TAC[INSERT_SUBSET]] THEN CONJ_TAC THENL [ASM_MESON_TAC[frontier; CLOSURE_EQ; IN_DIFF]; ASM_MESON_TAC[SUBSET_TRANS; INTERIOR_SUBSET]]);;
(* ------------------------------------------------------------------------- *) (* Special case of straight-line paths. *) (* ------------------------------------------------------------------------- *)
let linepath = new_definition
 `linepath(a,b) = \x. (&1 - drop x) % a + drop x % b`;;
let LINEPATH_TRANSLATION = 
prove (`!a b c. linepath(a + b,a + c) = (\x. a + x) o linepath(b,c)`,
REWRITE_TAC[linepath; o_THM; FUN_EQ_THM] THEN VECTOR_ARITH_TAC);;
add_translation_invariants [LINEPATH_TRANSLATION];;
let LINEPATH_LINEAR_IMAGE = 
prove (`!f. linear f ==> !b c. linepath(f b,f c) = f o linepath(b,c)`,
REWRITE_TAC[linepath; o_THM; FUN_EQ_THM] THEN REPEAT STRIP_TAC THEN FIRST_ASSUM(ASSUME_TAC o MATCH_MP LINEAR_ADD) THEN FIRST_ASSUM(ASSUME_TAC o MATCH_MP LINEAR_CMUL) THEN ASM_REWRITE_TAC[] THEN VECTOR_ARITH_TAC);;
add_linear_invariants [LINEPATH_LINEAR_IMAGE];;
let PATHSTART_LINEPATH = 
prove (`!a b. pathstart(linepath(a,b)) = a`,
REWRITE_TAC[linepath; pathstart; DROP_VEC] THEN VECTOR_ARITH_TAC);;
let PATHFINISH_LINEPATH = 
prove (`!a b. pathfinish(linepath(a,b)) = b`,
REWRITE_TAC[linepath; pathfinish; DROP_VEC] THEN VECTOR_ARITH_TAC);;
let CONTINUOUS_LINEPATH_AT = 
prove (`!a b x. linepath(a,b) continuous (at x)`,
REPEAT GEN_TAC THEN REWRITE_TAC[linepath] THEN REWRITE_TAC[VECTOR_ARITH `(&1 - u) % x + y = x + u % --x + y`] THEN MATCH_MP_TAC CONTINUOUS_ADD THEN REWRITE_TAC[CONTINUOUS_CONST] THEN MATCH_MP_TAC CONTINUOUS_ADD THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_VMUL THEN REWRITE_TAC[o_DEF; LIFT_DROP; CONTINUOUS_AT_ID]);;
let CONTINUOUS_ON_LINEPATH = 
prove (`!a b s. linepath(a,b) continuous_on s`,
let PATH_LINEPATH = 
prove (`!a b. path(linepath(a,b))`,
REWRITE_TAC[path; CONTINUOUS_ON_LINEPATH]);;
let PATH_IMAGE_LINEPATH = 
prove (`!a b. path_image(linepath (a,b)) = segment[a,b]`,
REWRITE_TAC[segment; path_image; linepath] THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM; IN_INTERVAL] THEN SIMP_TAC[DIMINDEX_1; FORALL_1; VEC_COMPONENT; ARITH] THEN REWRITE_TAC[EXISTS_LIFT; GSYM drop; LIFT_DROP] THEN MESON_TAC[]);;
let REVERSEPATH_LINEPATH = 
prove (`!a b. reversepath(linepath(a,b)) = linepath(b,a)`,
REWRITE_TAC[reversepath; linepath; DROP_SUB; DROP_VEC; FUN_EQ_THM] THEN VECTOR_ARITH_TAC);;
let ARC_LINEPATH = 
prove (`!a b. ~(a = b) ==> arc(linepath(a,b))`,
REWRITE_TAC[arc; PATH_LINEPATH] THEN REWRITE_TAC[linepath] THEN REWRITE_TAC[VECTOR_ARITH `(&1 - x) % a + x % b:real^N = (&1 - y) % a + y % b <=> (x - y) % (a - b) = vec 0`] THEN SIMP_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ; DROP_EQ; REAL_SUB_0]);;
let SIMPLE_PATH_LINEPATH = 
prove (`!a b. ~(a = b) ==> simple_path(linepath(a,b))`,
let SIMPLE_PATH_LINEPATH_EQ = 
prove (`!a b:real^N. simple_path(linepath(a,b)) <=> ~(a = b)`,
REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[SIMPLE_PATH_LINEPATH] THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[simple_path] THEN DISCH_THEN SUBST1_TAC THEN DISCH_THEN(MP_TAC o CONJUNCT2) THEN REWRITE_TAC[linepath; GSYM VECTOR_ADD_RDISTRIB] THEN DISCH_THEN(MP_TAC o SPECL [`lift(&0)`; `lift(&1 / &2)`]) THEN REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP; GSYM DROP_EQ; DROP_VEC] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
let ARC_LINEPATH_EQ = 
prove (`!a b. arc(linepath(a,b)) <=> ~(a = b)`,
REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[ARC_LINEPATH] THEN MESON_TAC[SIMPLE_PATH_LINEPATH_EQ; ARC_IMP_SIMPLE_PATH]);;
let LINEPATH_REFL = 
prove (`!a. linepath(a,a) = \x. a`,
REWRITE_TAC[linepath; VECTOR_ARITH `(&1 - u) % x + u % x:real^N = x`]);;
let SHIFTPATH_TRIVIAL = 
prove (`!t a. shiftpath t (linepath(a,a)) = linepath(a,a)`,
REWRITE_TAC[shiftpath; LINEPATH_REFL; COND_ID]);;
let SUBPATH_REFL = 
prove (`!g a. subpath a a g = linepath(g a,g a)`,
(* ------------------------------------------------------------------------- *) (* Bounding a point away from a path. *) (* ------------------------------------------------------------------------- *)
let NOT_ON_PATH_BALL = 
prove (`!g z:real^N. path g /\ ~(z IN path_image g) ==> ?e. &0 < e /\ ball(z,e) INTER (path_image g) = {}`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`path_image g:real^N->bool`; `z:real^N`] DISTANCE_ATTAINS_INF) THEN REWRITE_TAC[PATH_IMAGE_NONEMPTY] THEN ASM_SIMP_TAC[COMPACT_PATH_IMAGE; COMPACT_IMP_CLOSED] THEN DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN EXISTS_TAC `dist(z:real^N,a)` THEN CONJ_TAC THENL [ASM_MESON_TAC[DIST_POS_LT]; ALL_TAC] THEN REWRITE_TAC[EXTENSION; NOT_IN_EMPTY; IN_BALL; IN_INTER] THEN ASM_MESON_TAC[REAL_NOT_LE]);;
let NOT_ON_PATH_CBALL = 
prove (`!g z:real^N. path g /\ ~(z IN path_image g) ==> ?e. &0 < e /\ cball(z,e) INTER (path_image g) = {}`,
REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP NOT_ON_PATH_BALL) THEN DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `e / &2` THEN ASM_REWRITE_TAC[REAL_HALF] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `s INTER u = {} ==> t SUBSET s ==> t INTER u = {}`)) THEN REWRITE_TAC[SUBSET; IN_BALL; IN_CBALL] THEN UNDISCH_TAC `&0 < e` THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *) (* Homeomorphisms of arc images. *) (* ------------------------------------------------------------------------- *)
let HOMEOMORPHISM_ARC = 
prove (`!g:real^1->real^N. arc g ==> ?h. homeomorphism (interval[vec 0,vec 1],path_image g) (g,h)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHISM_COMPACT THEN ASM_REWRITE_TAC[path_image; COMPACT_INTERVAL; GSYM path; GSYM arc]);;
let HOMEOMORPHIC_ARC_IMAGE_INTERVAL = 
prove (`!g:real^1->real^N a b:real^1. arc g /\ drop a < drop b ==> (path_image g) homeomorphic interval[a,b]`,
REPEAT STRIP_TAC THEN TRANS_TAC HOMEOMORPHIC_TRANS `interval[vec 0:real^1,vec 1]` THEN CONJ_TAC THENL [ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN REWRITE_TAC[homeomorphic] THEN EXISTS_TAC `g:real^1->real^N` THEN ASM_SIMP_TAC[HOMEOMORPHISM_ARC]; MATCH_MP_TAC HOMEOMORPHIC_CLOSED_INTERVALS THEN ASM_REWRITE_TAC[INTERVAL_NE_EMPTY_1; DROP_VEC; REAL_LT_01]]);;
let HOMEOMORPHIC_ARC_IMAGES = 
prove (`!g:real^1->real^M h:real^1->real^N. arc g /\ arc h ==> (path_image g) homeomorphic (path_image h)`,
REPEAT STRIP_TAC THEN TRANS_TAC HOMEOMORPHIC_TRANS `interval[vec 0:real^1,vec 1]` THEN CONJ_TAC THENL [ALL_TAC; ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM]] THEN MATCH_MP_TAC HOMEOMORPHIC_ARC_IMAGE_INTERVAL THEN ASM_REWRITE_TAC[DROP_VEC; REAL_LT_01]);;
let HOMEOMORPHIC_ARC_IMAGE_SEGMENT = 
prove (`!g:real^1->real^N a b:real^M. arc g /\ ~(a = b) ==> (path_image g) homeomorphic segment[a,b]`,
REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM PATH_IMAGE_LINEPATH] THEN MATCH_MP_TAC HOMEOMORPHIC_ARC_IMAGES THEN ASM_REWRITE_TAC[ARC_LINEPATH_EQ]);;
(* ------------------------------------------------------------------------- *) (* Path component, considered as a "joinability" relation (from Tom Hales). *) (* ------------------------------------------------------------------------- *)
let path_component = new_definition
 `path_component s x y <=>
        ?g. path g /\ path_image g SUBSET s /\
            pathstart g = x /\ pathfinish g = y`;;
let PATH_COMPONENT_IN = 
prove (`!s x y. path_component s x y ==> x IN s /\ y IN s`,
REWRITE_TAC[path_component; path_image; pathstart; pathfinish] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN REPEAT(FIRST_X_ASSUM(SUBST1_TAC o SYM)) THEN FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; REAL_LE_REFL; REAL_POS]);;
let PATH_COMPONENT_REFL = 
prove (`!s x:real^N. x IN s ==> path_component s x x`,
REPEAT STRIP_TAC THEN REWRITE_TAC[path_component] THEN EXISTS_TAC `(\u. x):real^1->real^N` THEN REWRITE_TAC[pathstart; pathfinish; path_image; path; CONTINUOUS_ON_CONST; IMAGE; FORALL_IN_IMAGE] THEN REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN ASM_MESON_TAC[]);;
let PATH_COMPONENT_REFL_EQ = 
prove (`!s x:real^N. path_component s x x <=> x IN s`,
let PATH_COMPONENT_SYM = 
prove (`!s x y:real^N. path_component s x y ==> path_component s y x`,
let PATH_COMPONENT_SYM_EQ = 
prove (`!s x y. path_component s x y <=> path_component s y x`,
MESON_TAC[PATH_COMPONENT_SYM]);;
let PATH_COMPONENT_TRANS = 
prove (`!s x y:real^N. path_component s x y /\ path_component s y z ==> path_component s x z`,
REPEAT GEN_TAC THEN REWRITE_TAC[path_component] THEN DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `g1:real^1->real^N`) (X_CHOOSE_TAC `g2:real^1->real^N`)) THEN EXISTS_TAC `g1 ++ g2 :real^1->real^N` THEN ASM_SIMP_TAC[PATH_JOIN; PATH_IMAGE_JOIN; UNION_SUBSET; PATHSTART_JOIN; PATHFINISH_JOIN]);;
let PATH_COMPONENT_OF_SUBSET = 
prove (`!s t x. s SUBSET t /\ path_component s x y ==> path_component t x y`,
REWRITE_TAC[path_component] THEN SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Can also consider it as a set, as the name suggests. *) (* ------------------------------------------------------------------------- *)
let PATH_COMPONENT_SET = 
prove (`!s x. path_component s x = { y | ?g. path g /\ path_image g SUBSET s /\ pathstart g = x /\ pathfinish g = y }`,
REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REWRITE_TAC[IN; path_component]);;
let PATH_COMPONENT_SUBSET = 
prove (`!s x. (path_component s x) SUBSET s`,
REWRITE_TAC[SUBSET; IN] THEN MESON_TAC[PATH_COMPONENT_IN; IN]);;
let PATH_COMPONENT_EQ_EMPTY = 
prove (`!s x. path_component s x = {} <=> ~(x IN s)`,
REWRITE_TAC[EXTENSION; NOT_IN_EMPTY] THEN MESON_TAC[IN; PATH_COMPONENT_REFL; PATH_COMPONENT_IN]);;
let PATH_COMPONENT_EMPTY = 
prove (`!x. path_component {} x = {}`,
let UNIONS_PATH_COMPONENT = 
prove (`!s:real^N->bool. UNIONS {path_component s x |x| x IN s} = s`,
GEN_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[UNIONS_SUBSET; FORALL_IN_GSPEC; PATH_COMPONENT_SUBSET] THEN REWRITE_TAC[SUBSET; UNIONS_GSPEC; IN_ELIM_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[IN] THEN ASM_REWRITE_TAC[PATH_COMPONENT_REFL_EQ]);;
let PATH_COMPONENT_TRANSLATION = 
prove (`!a s x. path_component (IMAGE (\x. a + x) s) (a + x) = IMAGE (\x. a + x) (path_component s x)`,
REWRITE_TAC[PATH_COMPONENT_SET] THEN GEOM_TRANSLATE_TAC[]);;
add_translation_invariants [PATH_COMPONENT_TRANSLATION];;
let PATH_COMPONENT_LINEAR_IMAGE = 
prove (`!f s x. linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y) ==> path_component (IMAGE f s) (f x) = IMAGE f (path_component s x)`,
REWRITE_TAC[PATH_COMPONENT_SET] THEN GEOM_TRANSFORM_TAC[]);;
add_linear_invariants [PATH_COMPONENT_LINEAR_IMAGE];; (* ------------------------------------------------------------------------- *) (* Path connectedness of a space. *) (* ------------------------------------------------------------------------- *)
let path_connected = new_definition
 `path_connected s <=>
        !x y. x IN s /\ y IN s
              ==> ?g. path g /\ (path_image g) SUBSET s /\
                      pathstart g = x /\ pathfinish g = y`;;
let PATH_CONNECTED_IFF_PATH_COMPONENT = 
prove (`!s. path_connected s <=> !x y. x IN s /\ y IN s ==> path_component s x y`,
REWRITE_TAC[path_connected; path_component]);;
let PATH_CONNECTED_COMPONENT_SET = 
prove (`!s. path_connected s <=> !x. x IN s ==> path_component s x = s`,
REWRITE_TAC[PATH_CONNECTED_IFF_PATH_COMPONENT; GSYM SUBSET_ANTISYM_EQ] THEN REWRITE_TAC[PATH_COMPONENT_SUBSET] THEN SET_TAC[]);;
let PATH_COMPONENT_MONO = 
prove (`!s t x. s SUBSET t ==> (path_component s x) SUBSET (path_component t x)`,
REWRITE_TAC[PATH_COMPONENT_SET] THEN SET_TAC[]);;
let PATH_COMPONENT_MAXIMAL = 
prove (`!s t x. x IN t /\ path_connected t /\ t SUBSET s ==> t SUBSET (path_component s x)`,
REWRITE_TAC[path_connected; PATH_COMPONENT_SET; SUBSET; IN_ELIM_THM] THEN MESON_TAC[]);;
let PATH_COMPONENT_EQ = 
prove (`!s x y. y IN path_component s x ==> path_component s y = path_component s x`,
REWRITE_TAC[EXTENSION; IN] THEN MESON_TAC[PATH_COMPONENT_SYM; PATH_COMPONENT_TRANS]);;
let PATH_COMPONENT_PATH_IMAGE_PATHSTART = 
prove (`!p x:real^N. path p /\ x IN path_image p ==> path_component (path_image p) (pathstart p) x`,
REWRITE_TAC[path_image; IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN REPEAT STRIP_TAC THEN ASM_CASES_TAC `x:real^1 = vec 0` THENL [ASM_REWRITE_TAC[pathstart] THEN MATCH_MP_TAC PATH_COMPONENT_REFL THEN MATCH_MP_TAC FUN_IN_IMAGE THEN REWRITE_TAC[IN_INTERVAL_1] THEN REWRITE_TAC[DROP_VEC; REAL_POS]; ALL_TAC] THEN REWRITE_TAC[path_component] THEN EXISTS_TAC `\y. (p:real^1->real^N)(drop x % y)` THEN ASM_REWRITE_TAC[path; path_image; pathstart; pathfinish] THEN REWRITE_TAC[VECTOR_MUL_RZERO] THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_COMPOSE) THEN ASM_SIMP_TAC[CONTINUOUS_ON_CMUL; CONTINUOUS_ON_ID] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [path]) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET); ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o] THEN MATCH_MP_TAC IMAGE_SUBSET; AP_TERM_TAC THEN REWRITE_TAC[GSYM DROP_EQ; DROP_CMUL; DROP_VEC] THEN REWRITE_TAC[REAL_MUL_RID]] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN SIMP_TAC[IN_INTERVAL_1; DROP_CMUL; DROP_VEC; REAL_LE_MUL] THEN REPEAT STRIP_TAC THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_REWRITE_TAC[]);;
let PATH_CONNECTED_PATH_IMAGE = 
prove (`!p:real^1->real^N. path p ==> path_connected(path_image p)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[PATH_CONNECTED_IFF_PATH_COMPONENT] THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN MATCH_MP_TAC PATH_COMPONENT_TRANS THEN EXISTS_TAC `pathstart p :real^N` THEN ASM_MESON_TAC[PATH_COMPONENT_PATH_IMAGE_PATHSTART; PATH_COMPONENT_SYM]);;
let PATH_CONNECTED_PATH_COMPONENT = 
prove (`!s x:real^N. path_connected(path_component s x)`,
REPEAT GEN_TAC THEN REWRITE_TAC[path_connected; IN] THEN MAP_EVERY X_GEN_TAC [`y:real^N`; `z:real^N`] THEN STRIP_TAC THEN SUBGOAL_THEN `path_component s y (z:real^N)` MP_TAC THENL [ASM_MESON_TAC[PATH_COMPONENT_SYM; PATH_COMPONENT_TRANS]; ALL_TAC] THEN REWRITE_TAC[path_component] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `p:real^1->real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[SUBSET] THEN X_GEN_TAC `w:real^N` THEN DISCH_TAC THEN SUBGOAL_THEN `path_component s (x:real^N) = path_component s y` SUBST1_TAC THENL [ASM_MESON_TAC[PATH_COMPONENT_EQ; IN]; ALL_TAC] THEN MP_TAC(ISPECL [`p:real^1->real^N`; `w:real^N`] PATH_COMPONENT_PATH_IMAGE_PATHSTART) THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[IN] THEN FIRST_ASSUM(MP_TAC o MATCH_MP PATH_COMPONENT_MONO) THEN REWRITE_TAC[SUBSET; IN] THEN MESON_TAC[]);;
let PATH_COMPONENT = 
prove (`!s x y:real^N. path_component s x y <=> ?t. path_connected t /\ t SUBSET s /\ x IN t /\ y IN t`,
REPEAT GEN_TAC THEN EQ_TAC THEN STRIP_TAC THENL [EXISTS_TAC `path_component s (x:real^N)` THEN REWRITE_TAC[PATH_CONNECTED_PATH_COMPONENT; PATH_COMPONENT_SUBSET] THEN FIRST_ASSUM(MP_TAC o MATCH_MP PATH_COMPONENT_IN) THEN ASM_SIMP_TAC[IN; PATH_COMPONENT_REFL_EQ]; REWRITE_TAC[path_component] THEN ASM_MESON_TAC[path_connected; SUBSET]]);;
let PATH_COMPONENT_PATH_COMPONENT = 
prove (`!s x:real^N. path_component (path_component s x) x = path_component s x`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THENL [MATCH_MP_TAC SUBSET_ANTISYM THEN SIMP_TAC[PATH_COMPONENT_MONO; PATH_COMPONENT_SUBSET] THEN MATCH_MP_TAC PATH_COMPONENT_MAXIMAL THEN REWRITE_TAC[SUBSET_REFL; PATH_CONNECTED_PATH_COMPONENT] THEN ASM_REWRITE_TAC[IN; PATH_COMPONENT_REFL_EQ]; MATCH_MP_TAC(SET_RULE `s = {} /\ t = {} ==> s = t`) THEN ASM_REWRITE_TAC[PATH_COMPONENT_EQ_EMPTY] THEN ASM_MESON_TAC[SUBSET; PATH_COMPONENT_SUBSET]]);;
let PATH_CONNECTED_LINEPATH = 
prove (`!s a b:real^N. segment[a,b] SUBSET s ==> path_component s a b`,
REPEAT STRIP_TAC THEN REWRITE_TAC[path_component] THEN EXISTS_TAC `linepath(a:real^N,b)` THEN ASM_REWRITE_TAC[PATHSTART_LINEPATH; PATHFINISH_LINEPATH; PATH_LINEPATH] THEN ASM_REWRITE_TAC[PATH_IMAGE_LINEPATH]);;
let PATH_COMPONENT_DISJOINT = 
prove (`!s a b. DISJOINT (path_component s a) (path_component s b) <=> ~(a IN path_component s b)`,
REWRITE_TAC[DISJOINT; EXTENSION; IN_INTER; NOT_IN_EMPTY] THEN REWRITE_TAC[IN] THEN MESON_TAC[PATH_COMPONENT_SYM; PATH_COMPONENT_TRANS]);;
let PATH_COMPONENT_EQ_EQ = 
prove (`!s x y:real^N. path_component s x = path_component s y <=> ~(x IN s) /\ ~(y IN s) \/ x IN s /\ y IN s /\ path_component s x y`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `(y:real^N) IN s` THENL [ASM_CASES_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[] THENL [REWRITE_TAC[FUN_EQ_THM] THEN ASM_MESON_TAC[PATH_COMPONENT_TRANS; PATH_COMPONENT_REFL; PATH_COMPONENT_SYM]; ASM_MESON_TAC[PATH_COMPONENT_EQ_EMPTY]]; RULE_ASSUM_TAC(REWRITE_RULE[GSYM PATH_COMPONENT_EQ_EMPTY]) THEN ASM_REWRITE_TAC[PATH_COMPONENT_EQ_EMPTY] THEN ONCE_REWRITE_TAC[PATH_COMPONENT_SYM_EQ] THEN ASM_REWRITE_TAC[EMPTY] THEN ASM_MESON_TAC[PATH_COMPONENT_EQ_EMPTY]]);;
(* ------------------------------------------------------------------------- *) (* General "locally connected implies connected" type results. *) (* ------------------------------------------------------------------------- *)
let OPEN_GENERAL_COMPONENT = 
prove (`!c. (!s x y. c s x y ==> x IN s /\ y IN s) /\ (!s x y. c s x y ==> c s y x) /\ (!s x y z. c s x y /\ c s y z ==> c s x z) /\ (!s t x y. s SUBSET t /\ c s x y ==> c t x y) /\ (!s x y e. y IN ball(x,e) /\ ball(x,e) SUBSET s ==> c (ball(x,e)) x y) ==> !s x:real^N. open s ==> open(c s x)`,
GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "IN") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "SYM") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "TRANS") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "SUBSET") (LABEL_TAC "BALL")) THEN REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL; SUBSET; IN_BALL] THEN DISCH_TAC THEN X_GEN_TAC `y:real^N` THEN REWRITE_TAC[SUBSET; IN] THEN STRIP_TAC THEN SUBGOAL_THEN `(x:real^N) IN s /\ y IN s` STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN FIRST_X_ASSUM(MP_TAC o C MATCH_MP (ASSUME `(y:real^N) IN s`)) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN REMOVE_THEN "TRANS" MATCH_MP_TAC THEN EXISTS_TAC `y:real^N` THEN ASM_REWRITE_TAC[] THEN REMOVE_THEN "SUBSET" MATCH_MP_TAC THEN EXISTS_TAC `ball(y:real^N,e)` THEN ASM_REWRITE_TAC[SUBSET; IN_BALL] THEN REMOVE_THEN "BALL" MATCH_MP_TAC THEN REWRITE_TAC[SUBSET; IN_BALL] THEN ASM_MESON_TAC[]);;
let OPEN_NON_GENERAL_COMPONENT = 
prove (`!c. (!s x y. c s x y ==> x IN s /\ y IN s) /\ (!s x y. c s x y ==> c s y x) /\ (!s x y z. c s x y /\ c s y z ==> c s x z) /\ (!s t x y. s SUBSET t /\ c s x y ==> c t x y) /\ (!s x y e. y IN ball(x,e) /\ ball(x,e) SUBSET s ==> c (ball(x,e)) x y) ==> !s x:real^N. open s ==> open(s DIFF c s x)`,
GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "IN") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "SYM") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "TRANS") MP_TAC) THEN DISCH_THEN(CONJUNCTS_THEN2 (LABEL_TAC "SUBSET") (LABEL_TAC "BALL")) THEN REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL; SUBSET; IN_BALL] THEN DISCH_TAC THEN X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_DIFF] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (ASSUME_TAC o REWRITE_RULE[IN])) THEN FIRST_X_ASSUM(MP_TAC o C MATCH_MP (ASSUME `(y:real^N) IN s`)) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN ASM_SIMP_TAC[] THEN REWRITE_TAC[IN] THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN REWRITE_TAC[] THEN REMOVE_THEN "TRANS" MATCH_MP_TAC THEN EXISTS_TAC `z:real^N` THEN ASM_REWRITE_TAC[] THEN REMOVE_THEN "SUBSET" MATCH_MP_TAC THEN EXISTS_TAC `ball(y:real^N,e)` THEN ASM_REWRITE_TAC[SUBSET; IN_BALL] THEN REMOVE_THEN "SYM" MATCH_MP_TAC THEN REMOVE_THEN "BALL" MATCH_MP_TAC THEN REWRITE_TAC[SUBSET; IN_BALL] THEN ASM_MESON_TAC[]);;
let GENERAL_CONNECTED_OPEN = 
prove (`!c. (!s x y. c s x y ==> x IN s /\ y IN s) /\ (!s x y. c s x y ==> c s y x) /\ (!s x y z. c s x y /\ c s y z ==> c s x z) /\ (!s t x y. s SUBSET t /\ c s x y ==> c t x y) /\ (!s x y e. y IN ball(x,e) /\ ball(x,e) SUBSET s ==> c (ball(x,e)) x y) ==> !s x y:real^N. open s /\ connected s /\ x IN s /\ y IN s ==> c s x y`,
REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [connected]) THEN REWRITE_TAC[IN] THEN REWRITE_TAC[NOT_EXISTS_THM; LEFT_IMP_FORALL_THM] THEN MAP_EVERY EXISTS_TAC [`c (s:real^N->bool) (x:real^N):real^N->bool`; `s DIFF (c (s:real^N->bool) (x:real^N))`] THEN MATCH_MP_TAC(TAUT `a /\ b /\ c /\ d /\ e /\ (f ==> g) ==> ~(a /\ b /\ c /\ d /\ e /\ ~f) ==> g`) THEN REPEAT CONJ_TAC THENL [MP_TAC(SPEC `c:(real^N->bool)->real^N->real^N->bool` OPEN_GENERAL_COMPONENT) THEN ASM_MESON_TAC[]; MP_TAC(SPEC `c:(real^N->bool)->real^N->real^N->bool` OPEN_NON_GENERAL_COMPONENT) THEN ASM_MESON_TAC[]; SET_TAC[]; SET_TAC[]; ALL_TAC; ASM SET_TAC[]] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_INTER] THEN REWRITE_TAC[IN] THEN FIRST_ASSUM(MATCH_MP_TAC o SPECL [`ball(x:real^N,e)`; `s:real^N->bool`]) THEN ASM_MESON_TAC[CENTRE_IN_BALL]);;
(* ------------------------------------------------------------------------- *) (* Some useful lemmas about path-connectedness. *) (* ------------------------------------------------------------------------- *)
let CONVEX_IMP_PATH_CONNECTED = 
prove (`!s:real^N->bool. convex s ==> path_connected s`,
REWRITE_TAC[CONVEX_ALT; path_connected] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN EXISTS_TAC `\u. (&1 - drop u) % x + drop u % y:real^N` THEN ASM_SIMP_TAC[pathstart; pathfinish; DROP_VEC; path; path_image; SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; GSYM FORALL_DROP] THEN CONJ_TAC THENL [ALL_TAC; CONJ_TAC THEN VECTOR_ARITH_TAC] THEN MATCH_MP_TAC CONTINUOUS_ON_ADD THEN CONJ_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_VMUL THEN REWRITE_TAC[o_DEF; LIFT_SUB; LIFT_DROP; LIFT_NUM] THEN SIMP_TAC[CONTINUOUS_ON_SUB; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID]);;
let PATH_CONNECTED_UNIV = 
prove (`path_connected(:real^N)`,
let IS_INTERVAL_PATH_CONNECTED = 
prove (`!s. is_interval s ==> path_connected s`,
let PATH_CONNECTED_INTERVAL = 
prove (`(!a b:real^N. path_connected(interval[a,b])) /\ (!a b:real^N. path_connected(interval(a,b)))`,
let PATH_COMPONENT_UNIV = 
prove (`!x. path_component(:real^N) x = (:real^N)`,
let PATH_CONNECTED_IMP_CONNECTED = 
prove (`!s:real^N->bool. path_connected s ==> connected s`,
GEN_TAC THEN REWRITE_TAC[path_connected; CONNECTED_IFF_CONNECTED_COMPONENT] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `x:real^N` THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `y:real^N` THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `g:real^1->real^N` STRIP_ASSUME_TAC) THEN REWRITE_TAC[connected_component] THEN EXISTS_TAC `path_image(g:real^1->real^N)` THEN ASM_MESON_TAC[CONNECTED_PATH_IMAGE; PATHSTART_IN_PATH_IMAGE; PATHFINISH_IN_PATH_IMAGE]);;
let OPEN_PATH_COMPONENT = 
prove (`!s x:real^N. open s ==> open(path_component s x)`,
MATCH_MP_TAC OPEN_GENERAL_COMPONENT THEN REWRITE_TAC[PATH_COMPONENT_IN; PATH_COMPONENT_SYM; PATH_COMPONENT_TRANS; PATH_COMPONENT_OF_SUBSET] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC(REWRITE_RULE[PATH_CONNECTED_IFF_PATH_COMPONENT] (MATCH_MP CONVEX_IMP_PATH_CONNECTED (SPEC_ALL CONVEX_BALL))) THEN ASM_MESON_TAC[CENTRE_IN_BALL; BALL_EQ_EMPTY; REAL_NOT_LE; NOT_IN_EMPTY]);;
let OPEN_NON_PATH_COMPONENT = 
prove (`!s x:real^N. open s ==> open(s DIFF path_component s x)`,
let PATH_CONNECTED_CONTINUOUS_IMAGE = 
prove (`!f:real^M->real^N s. f continuous_on s /\ path_connected s ==> path_connected (IMAGE f s)`,
REPEAT GEN_TAC THEN REWRITE_TAC[path_connected] THEN STRIP_TAC THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_IN_IMAGE] THEN X_GEN_TAC `x:real^M` THEN DISCH_TAC THEN X_GEN_TAC `y:real^M` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^M`; `y:real^M`]) THEN ASM_REWRITE_TAC[path; path_image; pathstart; pathfinish] THEN DISCH_THEN(X_CHOOSE_THEN `g:real^1->real^M` STRIP_ASSUME_TAC) THEN EXISTS_TAC `(f:real^M->real^N) o (g:real^1->real^M)` THEN CONJ_TAC THENL [MATCH_MP_TAC CONTINUOUS_ON_COMPOSE THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ASM_REWRITE_TAC[o_DEF] THEN ASM SET_TAC[]]);;
let HOMEOMORPHIC_PATH_CONNECTEDNESS = 
prove (`!s t. s homeomorphic t ==> (path_connected s <=> path_connected t)`,
let PATH_CONNECTED_LINEAR_IMAGE = 
prove (`!f:real^M->real^N s. path_connected s /\ linear f ==> path_connected(IMAGE f s)`,
let PATH_CONNECTED_LINEAR_IMAGE_EQ = 
prove (`!f s. linear f /\ (!x y. f x = f y ==> x = y) ==> (path_connected (IMAGE f s) <=> path_connected s)`,
MATCH_ACCEPT_TAC(LINEAR_INVARIANT_RULE PATH_CONNECTED_LINEAR_IMAGE));;
add_linear_invariants [PATH_CONNECTED_LINEAR_IMAGE_EQ];;
let PATH_CONNECTED_EMPTY = 
prove (`path_connected {}`,
REWRITE_TAC[path_connected; NOT_IN_EMPTY]);;
let PATH_CONNECTED_SING = 
prove (`!a:real^N. path_connected {a}`,
GEN_TAC THEN REWRITE_TAC[path_connected; IN_SING] THEN REPEAT STRIP_TAC THEN EXISTS_TAC `linepath(a:real^N,a)` THEN ASM_REWRITE_TAC[PATH_LINEPATH; PATHSTART_LINEPATH; PATHFINISH_LINEPATH] THEN REWRITE_TAC[SEGMENT_REFL; PATH_IMAGE_LINEPATH; SUBSET_REFL]);;
let PATH_CONNECTED_UNION = 
prove (`!s t. path_connected s /\ path_connected t /\ ~(s INTER t = {}) ==> path_connected (s UNION t)`,
let PATH_CONNECTED_TRANSLATION = 
prove (`!a s. path_connected s ==> path_connected (IMAGE (\x:real^N. a + x) s)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_CONTINUOUS_IMAGE THEN ASM_SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_ID; CONTINUOUS_ON_CONST]);;
let PATH_CONNECTED_TRANSLATION_EQ = 
prove (`!a s. path_connected (IMAGE (\x:real^N. a + x) s) <=> path_connected s`,
REWRITE_TAC[path_connected] THEN GEOM_TRANSLATE_TAC[]);;
add_translation_invariants [PATH_CONNECTED_TRANSLATION_EQ];;
let PATH_CONNECTED_PCROSS = 
prove (`!s:real^M->bool t:real^N->bool. path_connected s /\ path_connected t ==> path_connected (s PCROSS t)`,
REPEAT GEN_TAC THEN REWRITE_TAC[PCROSS; path_connected] THEN DISCH_TAC THEN REWRITE_TAC[FORALL_PASTECART; IN_ELIM_PASTECART_THM] THEN MAP_EVERY X_GEN_TAC [`x1:real^M`; `y1:real^N`; `x2:real^M`; `y2:real^N`] THEN STRIP_TAC THEN FIRST_X_ASSUM(CONJUNCTS_THEN2 (MP_TAC o SPECL [`x1:real^M`; `x2:real^M`]) (MP_TAC o SPECL [`y1:real^N`; `y2:real^N`])) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `h:real^1->real^N` THEN STRIP_TAC THEN X_GEN_TAC `g:real^1->real^M` THEN STRIP_TAC THEN EXISTS_TAC `(\t. pastecart (x1:real^M) ((h:real^1->real^N) t)) ++ (\t. pastecart ((g:real^1->real^M) t) (y2:real^N))` THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish; path]) THEN RULE_ASSUM_TAC(REWRITE_RULE[path_image; FORALL_IN_IMAGE; SUBSET]) THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC PATH_JOIN_IMP THEN REPEAT CONJ_TAC THENL [REWRITE_TAC[path] THEN MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN ASM_REWRITE_TAC[CONTINUOUS_ON_CONST]; REWRITE_TAC[path] THEN MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN ASM_REWRITE_TAC[CONTINUOUS_ON_CONST]; ASM_REWRITE_TAC[pathstart; pathfinish]]; MATCH_MP_TAC SUBSET_PATH_IMAGE_JOIN THEN ASM_SIMP_TAC[path_image; FORALL_IN_IMAGE; SUBSET; IN_ELIM_PASTECART_THM]; REWRITE_TAC[PATHSTART_JOIN] THEN ASM_REWRITE_TAC[pathstart]; REWRITE_TAC[PATHFINISH_JOIN] THEN ASM_REWRITE_TAC[pathfinish]]);;
let PATH_CONNECTED_PCROSS_EQ = 
prove (`!s:real^M->bool t:real^N->bool. path_connected(s PCROSS t) <=> s = {} \/ t = {} \/ path_connected s /\ path_connected t`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[PCROSS_EMPTY; PATH_CONNECTED_EMPTY] THEN ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[PCROSS_EMPTY; PATH_CONNECTED_EMPTY] THEN EQ_TAC THEN REWRITE_TAC[PATH_CONNECTED_PCROSS] THEN REPEAT STRIP_TAC THENL [MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`; `(s:real^M->bool) PCROSS (t:real^N->bool)`] PATH_CONNECTED_LINEAR_IMAGE) THEN ASM_REWRITE_TAC[LINEAR_FSTCART]; MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`; `(s:real^M->bool) PCROSS (t:real^N->bool)`] PATH_CONNECTED_LINEAR_IMAGE) THEN ASM_REWRITE_TAC[LINEAR_SNDCART]] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; EXISTS_PASTECART; PASTECART_IN_PCROSS; FSTCART_PASTECART; SNDCART_PASTECART] THEN ASM SET_TAC[]);;
let PATH_CONNECTED_SCALING = 
prove (`!s:real^N->bool c. path_connected s ==> path_connected (IMAGE (\x. c % x) s)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
let PATH_CONNECTED_NEGATIONS = 
prove (`!s:real^N->bool. path_connected s ==> path_connected (IMAGE (--) s)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_CONTINUOUS_IMAGE THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONTINUOUS_AT_IMP_CONTINUOUS_ON THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC LINEAR_CONTINUOUS_AT THEN REWRITE_TAC[linear] THEN CONJ_TAC THEN VECTOR_ARITH_TAC);;
let PATH_CONNECTED_SUMS = 
prove (`!s t:real^N->bool. path_connected s /\ path_connected t ==> path_connected {x + y | x IN s /\ y IN t}`,
REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP PATH_CONNECTED_PCROSS) THEN DISCH_THEN(MP_TAC o ISPEC `\z. (fstcart z + sndcart z:real^N)` o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] PATH_CONNECTED_CONTINUOUS_IMAGE)) THEN SIMP_TAC[CONTINUOUS_ON_ADD; LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; LINEAR_SNDCART; PCROSS] THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_ELIM_THM; EXISTS_PASTECART] THEN REWRITE_TAC[PASTECART_INJ; FSTCART_PASTECART; SNDCART_PASTECART] THEN MESON_TAC[]);;
let IS_INTERVAL_PATH_CONNECTED_1 = 
prove (`!s:real^1->bool. is_interval s <=> path_connected s`,
(* ------------------------------------------------------------------------- *) (* More stuff about segments. *) (* ------------------------------------------------------------------------- *)
let SEGMENT_OPEN_SUBSET_CLOSED = 
prove (`!a b. segment(a,b) SUBSET segment[a,b]`,
REWRITE_TAC[CONJUNCT2(SPEC_ALL segment)] THEN SET_TAC[]);;
let CLOSED_SEGMENT = 
prove (`!a b. closed(segment[a,b])`,
REPEAT GEN_TAC THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC COMPACT_IMP_CLOSED THEN MATCH_MP_TAC COMPACT_CONVEX_HULL THEN MATCH_MP_TAC FINITE_IMP_COMPACT THEN SIMP_TAC[FINITE_RULES]);;
let SEGMENT_IMAGE_INTERVAL = 
prove (`(!a b. segment[a,b] = IMAGE (\u. (&1 - drop u) % a + drop u % b) (interval[vec 0,vec 1])) /\ (!a b. ~(a = b) ==> segment(a,b) = IMAGE (\u. (&1 - drop u) % a + drop u % b) (interval(vec 0,vec 1)))`,
REPEAT STRIP_TAC THEN REWRITE_TAC[EXTENSION; IN_IMAGE; IN_INTERVAL_1; IN_SEGMENT] THEN ASM_REWRITE_TAC[GSYM EXISTS_DROP; DROP_VEC] THEN MESON_TAC[]);;
let CLOSURE_SEGMENT = 
prove (`(!a b:real^N. closure(segment[a,b]) = segment[a,b]) /\ (!a b:real^N. closure(segment(a,b)) = if a = b then {} else segment[a,b])`,
REWRITE_TAC[CLOSURE_EQ; CLOSED_SEGMENT] THEN REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[SEGMENT_REFL; CLOSURE_EMPTY] THEN ASM_SIMP_TAC[SEGMENT_IMAGE_INTERVAL] THEN ASM_SIMP_TAC[CONV_RULE(RAND_CONV SYM_CONV) (SPEC_ALL CLOSURE_OPEN_INTERVAL); INTERVAL_EQ_EMPTY_1; DROP_VEC; REAL_ARITH `~(&1 <= &0)`] THEN SUBGOAL_THEN `(\u. (&1 - drop u) % a + drop u % (b:real^N)) = (\x. a + x) o (\u. drop u % (b - a))` SUBST1_TAC THENL [REWRITE_TAC[FUN_EQ_THM; o_THM] THEN VECTOR_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[IMAGE_o; CLOSURE_TRANSLATION] THEN AP_TERM_TAC THEN MATCH_MP_TAC CLOSURE_INJECTIVE_LINEAR_IMAGE THEN ASM_REWRITE_TAC[VECTOR_MUL_RCANCEL; VECTOR_SUB_EQ; DROP_EQ] THEN REWRITE_TAC[linear; DROP_ADD; DROP_CMUL] THEN VECTOR_ARITH_TAC);;
let AFFINE_HULL_SEGMENT = 
prove (`(!a b:real^N. affine hull (segment [a,b]) = affine hull {a,b}) /\ (!a b:real^N. affine hull (segment(a,b)) = if a = b then {} else affine hull {a,b})`,
REWRITE_TAC[SEGMENT_CONVEX_HULL; AFFINE_HULL_CONVEX_HULL] THEN REPEAT GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM AFFINE_HULL_CLOSURE] THEN REWRITE_TAC[CLOSURE_SEGMENT] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[AFFINE_HULL_EMPTY] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL; AFFINE_HULL_CONVEX_HULL]);;
let SEGMENT_AS_BALL = 
prove (`(!a b. segment[a:real^N,b] = affine hull {a,b} INTER cball(inv(&2) % (a + b),norm(b - a) / &2)) /\ (!a b. segment(a:real^N,b) = affine hull {a,b} INTER ball(inv(&2) % (a + b),norm(b - a) / &2))`,
REPEAT STRIP_TAC THEN (ASM_CASES_TAC `b:real^N = a` THEN ASM_REWRITE_TAC[SEGMENT_REFL; VECTOR_SUB_REFL; NORM_0] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[BALL_TRIVIAL; CBALL_TRIVIAL] THENL [REWRITE_TAC[INTER_EMPTY; INSERT_AC] THEN REWRITE_TAC[VECTOR_ARITH `&1 / &2 % (a + a) = a`] THEN REWRITE_TAC[SET_RULE `a = b INTER a <=> a SUBSET b`; HULL_SUBSET]; ASM_REWRITE_TAC[EXTENSION; IN_SEGMENT; IN_INTER; AFFINE_HULL_2] THEN X_GEN_TAC `y:real^N` THEN REWRITE_TAC[IN_ELIM_THM] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN REWRITE_TAC[REAL_ARITH `u + v:real = &1 <=> u = &1 - v`] THEN REWRITE_TAC[UNWIND_THM2] THEN REWRITE_TAC[LEFT_AND_EXISTS_THM] THEN AP_TERM_TAC THEN GEN_REWRITE_TAC I [FUN_EQ_THM] THEN X_GEN_TAC `u:real` THEN REWRITE_TAC[] THEN ASM_CASES_TAC `y:real^N = (&1 - u) % a + u % b` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[IN_BALL; IN_CBALL; dist; VECTOR_ARITH `&1 / &2 % (a + b) - ((&1 - u) % a + u % b):real^N = (&1 / &2 - u) % (b - a)`] THEN ASM_SIMP_TAC[NORM_MUL; REAL_LT_MUL_EQ; REAL_LE_MUL_EQ; NORM_POS_LT; VECTOR_SUB_EQ; REAL_ARITH `a * n < n / &2 <=> &0 < n * (inv(&2) - a)`; REAL_ARITH `a * n <= n / &2 <=> &0 <= n * (inv(&2) - a)`] THEN REAL_ARITH_TAC]));;
let CONVEX_SEGMENT = 
prove (`(!a b. convex(segment[a,b])) /\ (!a b. convex(segment(a,b)))`,
let RELATIVE_INTERIOR_SEGMENT = 
prove (`(!a b:real^N. relative_interior(segment[a,b]) = if a = b then {a} else segment(a,b)) /\ (!a b:real^N. relative_interior(segment(a,b)) = segment(a,b))`,
MATCH_MP_TAC(TAUT `b /\ (b ==> a) ==> a /\ b`) THEN CONJ_TAC THENL [REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[SEGMENT_REFL; RELATIVE_INTERIOR_EMPTY] THEN REWRITE_TAC[RELATIVE_INTERIOR_EQ; OPEN_IN_OPEN] THEN ASM_REWRITE_TAC[AFFINE_HULL_SEGMENT] THEN EXISTS_TAC `ball(inv(&2) % (a + b):real^N,norm(b - a) / &2)` THEN REWRITE_TAC[OPEN_BALL; SEGMENT_AS_BALL]; REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[SEGMENT_REFL; RELATIVE_INTERIOR_SING] THEN MP_TAC(ISPECL [`a:real^N`; `b:real^N`] (CONJUNCT2 CLOSURE_SEGMENT)) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN MATCH_MP_TAC CONVEX_RELATIVE_INTERIOR_CLOSURE THEN REWRITE_TAC[CONVEX_SEGMENT]]);;
let PATH_CONNECTED_SEGMENT = 
prove (`(!a b. path_connected(segment[a,b])) /\ (!a b. path_connected(segment(a,b)))`,
let CONNECTED_SEGMENT = 
prove (`(!a b. connected(segment[a,b])) /\ (!a b. connected(segment(a,b)))`,
let CONVEX_SEMIOPEN_SEGMENT = 
prove (`(!a b:real^N. convex(segment[a,b] DELETE a)) /\ (!a b:real^N. convex(segment[a,b] DELETE b))`,
MATCH_MP_TAC(TAUT `(a ==> b) /\ a ==> a /\ b`) THEN CONJ_TAC THENL [MESON_TAC[SEGMENT_SYM]; ALL_TAC] THEN REPEAT GEN_TAC THEN ASM_CASES_TAC `b:real^N = a` THEN ASM_SIMP_TAC[SEGMENT_REFL; SET_RULE `{a} DELETE a = {}`; CONVEX_EMPTY] THEN REWRITE_TAC[CONVEX_ALT; IN_DELETE] THEN SIMP_TAC[REWRITE_RULE[CONVEX_ALT] CONVEX_SEGMENT] THEN REWRITE_TAC[IN_SEGMENT] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[VECTOR_ADD_LDISTRIB; VECTOR_MUL_ASSOC; GSYM VECTOR_ADD_ASSOC] THEN ASM_REWRITE_TAC[VECTOR_ARITH `x % a + y % b + z % a + w % b:real^N = a <=> (&1 - x - z) % a = (w + y) % b`] THEN ASM_REWRITE_TAC[VECTOR_MUL_LCANCEL; REAL_ARITH `&1 - (&1 - u) * (&1 - v) - u * (&1 - w) = u * w + (&1 - u) * v`] THEN ASM_SIMP_TAC[REAL_LE_MUL; REAL_SUB_LE; REAL_ARITH `&0 <= x /\ &0 <= y ==> (x + y = &0 <=> x = &0 /\ y = &0)`] THEN REWRITE_TAC[REAL_ENTIRE; REAL_ARITH `&1 - x = &0 <=> x = &1`] THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH `(u = &0 \/ w = &0) /\ (u = &1 \/ v = &0) ==> u = &0 /\ v = &0 \/ u = &1 /\ w = &0 \/ v = &0 /\ w = &0`)) THEN DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN (CONJUNCTS_THEN SUBST_ALL_TAC)) THEN ASM_MESON_TAC[VECTOR_ARITH `(&1 - &0) % a + &0 % b:real^N = a`]);;
let PATH_CONNECTED_SEMIOPEN_SEGMENT = 
prove (`(!a b:real^N. path_connected(segment[a,b] DELETE a)) /\ (!a b:real^N. path_connected(segment[a,b] DELETE b))`,
let CONNECTED_SEMIOPEN_SEGMENT = 
prove (`(!a b:real^N. connected(segment[a,b] DELETE a)) /\ (!a b:real^N. connected(segment[a,b] DELETE b))`,
let SEGMENT_EQ_EMPTY = 
prove (`(!a b:real^N. ~(segment[a,b] = {})) /\ (!a b:real^N. segment(a,b) = {} <=> a = b)`,
REWRITE_TAC[SEGMENT_CONVEX_HULL; CONVEX_HULL_EQ_EMPTY; NOT_INSERT_EMPTY] THEN REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[SEGMENT_REFL] THEN ASM_MESON_TAC[NOT_IN_EMPTY; MIDPOINT_IN_SEGMENT]);;
let FINITE_SEGMENT = 
prove (`(!a b:real^N. FINITE(segment[a,b]) <=> a = b) /\ (!a b:real^N. FINITE(segment(a,b)) <=> a = b)`,
REWRITE_TAC[open_segment; SET_RULE `s DIFF {a,b} = s DELETE a DELETE b`] THEN REWRITE_TAC[FINITE_DELETE] THEN REPEAT GEN_TAC THEN ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[SEGMENT_REFL; FINITE_SING] THEN REWRITE_TAC[SEGMENT_IMAGE_INTERVAL] THEN W(MP_TAC o PART_MATCH (lhs o rand) FINITE_IMAGE_INJ_EQ o rand o snd) THEN ANTS_TAC THENL [REWRITE_TAC[VECTOR_ARITH `(&1 - u) % a + u % b:real^N = (&1 - v) % a + v % b <=> (u - v) % (b - a) = vec 0`] THEN ASM_SIMP_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ; REAL_SUB_0; DROP_EQ]; DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[FINITE_INTERVAL_1] THEN REWRITE_TAC[DROP_VEC] THEN REAL_ARITH_TAC]);;
let SEGMENT_EQ_SING = 
prove (`(!a b c:real^N. segment[a,b] = {c} <=> a = c /\ b = c) /\ (!a b c:real^N. ~(segment(a,b) = {c}))`,
REWRITE_TAC[SEGMENT_CONVEX_HULL; CONVEX_HULL_EQ_SING] THEN CONJ_TAC THENL [SET_TAC[]; REPEAT GEN_TAC] THEN ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[SEGMENT_REFL; NOT_INSERT_EMPTY] THEN DISCH_TAC THEN MP_TAC(ISPECL [`a:real^N`; `b:real^N`] (CONJUNCT2 FINITE_SEGMENT)) THEN ASM_REWRITE_TAC[FINITE_SING]);;
let SUBSET_SEGMENT_OPEN_CLOSED = 
prove (`!a b c d:real^N. segment(a,b) SUBSET segment(c,d) <=> a = b \/ segment[a,b] SUBSET segment[c,d]`,
REPEAT GEN_TAC THEN EQ_TAC THENL [ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o MATCH_MP SUBSET_CLOSURE) THEN ASM_REWRITE_TAC[CLOSURE_SEGMENT] THEN COND_CASES_TAC THEN REWRITE_TAC[SUBSET_EMPTY; SEGMENT_EQ_EMPTY]; ALL_TAC] THEN DISCH_THEN(DISJ_CASES_THEN2 SUBST1_TAC MP_TAC) THEN REWRITE_TAC[SEGMENT_REFL; EMPTY_SUBSET] THEN ABBREV_TAC `m:real^N = d - c` THEN POP_ASSUM MP_TAC THEN GEOM_NORMALIZE_TAC `m:real^N` THEN SIMP_TAC[VECTOR_SUB_EQ; SEGMENT_REFL; SEGMENT_EQ_SING; SEGMENT_EQ_EMPTY; SET_RULE `s SUBSET {a} <=> s = {a} \/ s = {}`; SUBSET_REFL] THEN X_GEN_TAC `m:real^N` THEN DISCH_TAC THEN REPEAT GEN_TAC THEN DISCH_THEN(SUBST_ALL_TAC o SYM) THEN POP_ASSUM MP_TAC THEN GEOM_ORIGIN_TAC `c:real^N` THEN GEOM_BASIS_MULTIPLE_TAC 1 `d:real^N` THEN X_GEN_TAC `d:real` THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN SIMP_TAC[VECTOR_SUB_RZERO; NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN ASM_REWRITE_TAC[real_abs; REAL_MUL_RID] THEN DISCH_THEN SUBST_ALL_TAC THEN POP_ASSUM(K ALL_TAC) THEN DISCH_TAC THEN SUBGOAL_THEN `collinear{vec 0:real^N,&1 % basis 1,x} /\ collinear{vec 0:real^N,&1 % basis 1,y}` MP_TAC THENL [ONCE_REWRITE_TAC[SET_RULE `{a,b,c} = {a,c,b}`] THEN CONJ_TAC THEN MATCH_MP_TAC BETWEEN_IMP_COLLINEAR THEN REWRITE_TAC[BETWEEN_IN_SEGMENT] THEN ASM_MESON_TAC[SUBSET; ENDS_IN_SEGMENT]; ALL_TAC] THEN SIMP_TAC[COLLINEAR_LEMMA_ALT; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL; VECTOR_ARITH `&1 % x:real^N = vec 0 <=> x = vec 0`] THEN REWRITE_TAC[IMP_CONJ; VECTOR_MUL_ASSOC; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `a:real` THEN REWRITE_TAC[REAL_MUL_RID] THEN DISCH_THEN SUBST_ALL_TAC THEN X_GEN_TAC `b:real` THEN DISCH_THEN SUBST_ALL_TAC THEN POP_ASSUM MP_TAC THEN SUBST1_TAC(VECTOR_ARITH `vec 0:real^N = &0 % basis 1`) THEN ASM_SIMP_TAC[SEGMENT_SCALAR_MULTIPLE; VECTOR_MUL_RCANCEL; BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL; SET_RULE `(!x y. x % v = y % v <=> x = y) ==> ({x % v | P x} SUBSET {x % v | Q x} <=> {x | P x} SUBSET {x | Q x})`] THEN REWRITE_TAC[REAL_ARITH `a <= x /\ x <= b \/ b <= x /\ x <= a <=> min a b <= x /\ x <= max a b`; REAL_ARITH `a < x /\ x < b \/ b < x /\ x < a <=> min a b < x /\ x < max a b`] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN DISCH_TAC THEN X_GEN_TAC `x:real` THEN FIRST_X_ASSUM(fun th -> MAP_EVERY (MP_TAC o C SPEC th) [`min (a:real) b`; `max (a:real) b`]) THEN REAL_ARITH_TAC);;
let SUBSET_SEGMENT = 
prove (`(!a b c d:real^N. segment[a,b] SUBSET segment[c,d] <=> a IN segment[c,d] /\ b IN segment[c,d]) /\ (!a b c d:real^N. segment[a,b] SUBSET segment(c,d) <=> a IN segment(c,d) /\ b IN segment(c,d)) /\ (!a b c d:real^N. segment(a,b) SUBSET segment[c,d] <=> a = b \/ a IN segment[c,d] /\ b IN segment[c,d]) /\ (!a b c d:real^N. segment(a,b) SUBSET segment(c,d) <=> a = b \/ a IN segment[c,d] /\ b IN segment[c,d])`,
MATCH_MP_TAC(TAUT `(a /\ b) /\ (a /\ b ==> c) ==> a /\ b /\ c`) THEN CONJ_TAC THENL [REPEAT STRIP_TAC THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [SEGMENT_CONVEX_HULL] THEN SIMP_TAC[SUBSET_HULL; CONVEX_SEGMENT] THEN SET_TAC[]; STRIP_TAC THEN ASM_REWRITE_TAC[SUBSET_SEGMENT_OPEN_CLOSED] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `closure(segment(a:real^N,b)) SUBSET segment[c,d]` THEN CONJ_TAC THENL [SIMP_TAC[CLOSURE_MINIMAL_EQ; CLOSED_SEGMENT]; ALL_TAC] THEN REWRITE_TAC[CLOSURE_SEGMENT] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[EMPTY_SUBSET]]);;
let INTERIOR_SEGMENT = 
prove (`(!a b:real^N. interior(segment[a,b]) = if 2 <= dimindex(:N) then {} else segment(a,b)) /\ (!a b:real^N. interior(segment(a,b)) = if 2 <= dimindex(:N) then {} else segment(a,b))`,
REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN ASM_CASES_TAC `2 <= dimindex(:N)` THEN ASM_REWRITE_TAC[] THENL [MATCH_MP_TAC(SET_RULE `t SUBSET s /\ s = {} ==> s = {} /\ t = {}`) THEN SIMP_TAC[SEGMENT_OPEN_SUBSET_CLOSED; SUBSET_INTERIOR] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC EMPTY_INTERIOR_CONVEX_HULL THEN REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY] THEN FIRST_ASSUM (MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ_ALT] LE_TRANS)) THEN SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN ARITH_TAC; ASM_CASES_TAC `a:real^N = b` THEN ASM_SIMP_TAC[SEGMENT_REFL; INTERIOR_EMPTY; EMPTY_INTERIOR_FINITE; FINITE_SING] THEN SUBGOAL_THEN `affine hull (segment[a,b]) = (:real^N) /\ affine hull (segment(a,b)) = (:real^N)` (fun th -> ASM_SIMP_TAC[th; GSYM RELATIVE_INTERIOR_INTERIOR; RELATIVE_INTERIOR_SEGMENT]) THEN ASM_REWRITE_TAC[AFFINE_HULL_SEGMENT] THEN MATCH_MP_TAC AFFINE_INDEPENDENT_SPAN_GT THEN REWRITE_TAC[AFFINE_INDEPENDENT_2] THEN ASM_SIMP_TAC[CARD_CLAUSES; FINITE_RULES; IN_INSERT; NOT_IN_EMPTY] THEN ASM_ARITH_TAC]);;
let SEGMENT_EQ = 
prove (`(!a b c d:real^N. segment[a,b] = segment[c,d] <=> {a,b} = {c,d}) /\ (!a b c d:real^N. ~(segment[a,b] = segment(c,d))) /\ (!a b c d:real^N. ~(segment(a,b) = segment[c,d])) /\ (!a b c d:real^N. segment(a,b) = segment(c,d) <=> a = b /\ c = d \/ {a,b} = {c,d})`,
MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL [REPEAT GEN_TAC THEN EQ_TAC THENL [DISCH_THEN(fun th -> MP_TAC th THEN MP_TAC(AP_TERM `\s:real^N->bool. s DIFF relative_interior s` th)) THEN REWRITE_TAC[RELATIVE_INTERIOR_SEGMENT] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[SEGMENT_REFL]) THEN SIMP_TAC[ENDS_IN_SEGMENT; open_segment; SET_RULE `a IN s /\ b IN s ==> s DIFF (s DIFF {a,b}) = {a,b}`] THEN ASM SET_TAC[SEGMENT_EQ_SING]; SIMP_TAC[SEGMENT_CONVEX_HULL]]; DISCH_TAC] THEN MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL [REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o AP_TERM `closed:(real^N->bool)->bool`) THEN REWRITE_TAC[CLOSED_SEGMENT] THEN REWRITE_TAC[GSYM CLOSURE_EQ; CLOSURE_SEGMENT] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL [ASM SET_TAC[SEGMENT_EQ_EMPTY]; REWRITE_TAC[open_segment; ENDS_IN_SEGMENT; SET_RULE `s = s DIFF {a,b} <=> ~(a IN s) /\ ~(b IN s)`]]; DISCH_TAC THEN CONJ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN REPEAT GEN_TAC THEN ASM_CASES_TAC `c:real^N = d` THEN ASM_REWRITE_TAC[SEGMENT_EQ_EMPTY; SEGMENT_REFL] THENL [ASM SET_TAC[]; ALL_TAC] THEN CONV_TAC(BINOP_CONV SYM_CONV)THEN ASM_CASES_TAC `a:real^N = b` THEN ASM_REWRITE_TAC[SEGMENT_EQ_EMPTY; SEGMENT_REFL] THENL [ASM SET_TAC[]; ALL_TAC] THEN ASM_REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; SUBSET_SEGMENT_OPEN_CLOSED] THEN ASM_REWRITE_TAC[SUBSET_ANTISYM_EQ]]);;
let COMPACT_SEGMENT = 
prove (`!a b. compact(segment[a,b])`,
let BOUNDED_SEGMENT = 
prove (`(!a b:real^N. bounded(segment[a,b])) /\ (!a b:real^N. bounded(segment(a,b)))`,
REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(MESON[BOUNDED_SUBSET] `bounded s /\ t SUBSET s ==> bounded s /\ bounded t`) THEN REWRITE_TAC[SEGMENT_OPEN_SUBSET_CLOSED] THEN MESON_TAC[COMPACT_IMP_BOUNDED; COMPACT_SEGMENT]);;
let COLLINEAR_SEGMENT = 
prove (`(!a b:real^N. collinear(segment[a,b])) /\ (!a b:real^N. collinear(segment(a,b)))`,
REWRITE_TAC[AND_FORALL_THM] THEN REPEAT GEN_TAC THEN MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL [REWRITE_TAC[COLLINEAR_AFFINE_HULL] THEN MAP_EVERY EXISTS_TAC [`a:real^N`; `b:real^N`] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL; CONVEX_HULL_SUBSET_AFFINE_HULL]; MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] COLLINEAR_SUBSET) THEN REWRITE_TAC[SEGMENT_OPEN_SUBSET_CLOSED]]);;
let UNION_SEGMENT = 
prove (`!a b c:real^N. b IN segment[a,c] ==> segment[a,b] UNION segment[b,c] = segment[a,c]`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `c:real^N = a` THENL [ASM_SIMP_TAC[SEGMENT_REFL; IN_SING; UNION_IDEMPOT]; ONCE_REWRITE_TAC[UNION_COMM] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN DISCH_THEN(SUBST1_TAC o MATCH_MP CONVEX_HULL_EXCHANGE_UNION) THEN ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN REWRITE_TAC[IMAGE_CLAUSES; UNIONS_2] THEN BINOP_TAC THEN AP_TERM_TAC THEN ASM SET_TAC[]]);;
let INTER_SEGMENT = 
prove (`!a b c:real^N. b IN segment[a,c] \/ ~collinear{a,b,c} ==> segment[a,b] INTER segment[b,c] = {b}`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `c:real^N = a` THENL [ASM_SIMP_TAC[SEGMENT_REFL; IN_SING; INTER_IDEMPOT; INSERT_AC; COLLINEAR_2]; ALL_TAC] THEN DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL [REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN DISCH_TAC THEN MP_TAC(ISPECL [`{a:real^N,c}`; `b:real^N`; `{a:real^N}`; `{c:real^N}`] CONVEX_HULL_EXCHANGE_INTER) THEN ASM_REWRITE_TAC[AFFINE_INDEPENDENT_2] THEN ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[INSERT_AC]] THEN DISCH_THEN SUBST1_TAC THEN ASM_SIMP_TAC[SET_RULE `~(a = c) ==> {a} INTER {c} = {}`] THEN REWRITE_TAC[CONVEX_HULL_SING]; ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE `~(s INTER t = {b}) ==> b IN s /\ b IN t ==> ?a. ~(a = b) /\ a IN s /\ b IN s /\ a IN t /\ b IN t`)) THEN ANTS_TAC THENL [REWRITE_TAC[ENDS_IN_SEGMENT]; ALL_TAC] THEN REWRITE_TAC[GSYM BETWEEN_IN_SEGMENT; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `d:real^N` THEN STRIP_TAC THEN REPEAT(FIRST_X_ASSUM(ASSUME_TAC o MATCH_MP BETWEEN_IMP_COLLINEAR)) THEN MATCH_MP_TAC COLLINEAR_3_TRANS THEN EXISTS_TAC `d:real^N` THEN REPEAT(POP_ASSUM MP_TAC) THEN SIMP_TAC[INSERT_AC]]);;
let SUBSET_CONTINUOUS_IMAGE_SEGMENT_1 = 
prove (`!f:real^N->real^1 a b. f continuous_on segment[a,b] ==> segment[f a,f b] SUBSET IMAGE f (segment[a,b])`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] CONNECTED_CONTINUOUS_IMAGE)) THEN REWRITE_TAC[CONNECTED_SEGMENT] THEN REWRITE_TAC[GSYM IS_INTERVAL_CONNECTED_1; IS_INTERVAL_CONVEX_1] THEN REWRITE_TAC[CONVEX_CONTAINS_SEGMENT] THEN MESON_TAC[IN_IMAGE; ENDS_IN_SEGMENT]);;
let CONTINUOUS_INJECTIVE_IMAGE_SEGMENT_1 = 
prove (`!f:real^N->real^1 a b. f continuous_on segment[a,b] /\ (!x y. x IN segment[a,b] /\ y IN segment[a,b] /\ f x = f y ==> x = y) ==> IMAGE f (segment[a,b]) = segment[f a,f b]`,
let lemma = prove
   (`!a b c:real^1.
      ~(a = b) /\ ~(a IN segment(c,b)) /\ ~(b IN segment(a,c))
      ==> c IN segment[a,b]`,
    REWRITE_TAC[FORALL_LIFT; SEGMENT_1; LIFT_DROP] THEN
    REPEAT GEN_TAC THEN REWRITE_TAC[SEGMENT_1; LIFT_EQ] THEN
    REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP]) THEN
    ASM_REAL_ARITH_TAC) in
  REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
  REWRITE_TAC[INJECTIVE_ON_LEFT_INVERSE; LEFT_IMP_EXISTS_THM] THEN
  X_GEN_TAC `g:real^1->real^N` THEN DISCH_TAC THEN
  MP_TAC(ISPECL [`f:real^N->real^1`; `g:real^1->real^N`;
                 `segment[a:real^N,b]`]
        CONTINUOUS_ON_INVERSE) THEN
  ASM_REWRITE_TAC[COMPACT_SEGMENT] THEN DISCH_TAC THEN
  REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN
  MATCH_MP_TAC(TAUT `q /\ (q ==> p) ==> p /\ q`) THEN CONJ_TAC THENL
   [ASM_SIMP_TAC[SUBSET_CONTINUOUS_IMAGE_SEGMENT_1]; DISCH_TAC] THEN
  ASM_CASES_TAC `a:real^N = b` THEN
  ASM_REWRITE_TAC[SEGMENT_REFL] THENL [SET_TAC[]; ALL_TAC] THEN
  REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN X_GEN_TAC `c:real^N` THEN
  DISCH_TAC THEN MATCH_MP_TAC lemma THEN
  MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
   [ASM_MESON_TAC[ENDS_IN_SEGMENT]; DISCH_TAC] THEN
  ONCE_REWRITE_TAC[segment] THEN
  ASM_REWRITE_TAC[IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN
  REPEAT STRIP_TAC THENL
   [MP_TAC(ISPECL [`f:real^N->real^1`; `c:real^N`; `b:real^N`]
        SUBSET_CONTINUOUS_IMAGE_SEGMENT_1) THEN
    SUBGOAL_THEN `segment[c:real^N,b] SUBSET segment[a,b]` ASSUME_TAC THENL
     [ASM_REWRITE_TAC[SUBSET_SEGMENT; ENDS_IN_SEGMENT]; ALL_TAC] THEN
    REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
     [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; REWRITE_TAC[SUBSET]] THEN
    DISCH_THEN(MP_TAC o SPEC `(f:real^N->real^1) a`) THEN
    ASM_REWRITE_TAC[IN_IMAGE; NOT_EXISTS_THM] THEN
    X_GEN_TAC `d:real^N` THEN ASM_CASES_TAC `d:real^N = a` THENL
     [ASM_MESON_TAC[BETWEEN_ANTISYM; BETWEEN_IN_SEGMENT];
      ASM_MESON_TAC[ENDS_IN_SEGMENT; SUBSET]];
    MP_TAC(ISPECL [`f:real^N->real^1`; `a:real^N`; `c:real^N`]
        SUBSET_CONTINUOUS_IMAGE_SEGMENT_1) THEN
    SUBGOAL_THEN `segment[a:real^N,c] SUBSET segment[a,b]` ASSUME_TAC THENL
     [ASM_REWRITE_TAC[SUBSET_SEGMENT; ENDS_IN_SEGMENT]; ALL_TAC] THEN
    REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
     [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; REWRITE_TAC[SUBSET]] THEN
    DISCH_THEN(MP_TAC o SPEC `(f:real^N->real^1) b`) THEN
    ASM_REWRITE_TAC[IN_IMAGE; NOT_EXISTS_THM] THEN
    X_GEN_TAC `d:real^N` THEN ASM_CASES_TAC `d:real^N = b` THENL
     [ASM_MESON_TAC[BETWEEN_ANTISYM; BETWEEN_IN_SEGMENT; BETWEEN_SYM];
      ASM_MESON_TAC[ENDS_IN_SEGMENT; SUBSET]]]);;
let CONTINUOUS_INJECTIVE_IMAGE_OPEN_SEGMENT_1 = 
prove (`!f:real^N->real^1 a b. f continuous_on segment[a,b] /\ (!x y. x IN segment[a,b] /\ y IN segment[a,b] /\ f x = f y ==> x = y) ==> IMAGE f (segment(a,b)) = segment(f a,f b)`,
REPEAT GEN_TAC THEN DISCH_TAC THEN ONCE_REWRITE_TAC[segment] THEN FIRST_ASSUM(MP_TAC o MATCH_MP CONTINUOUS_INJECTIVE_IMAGE_SEGMENT_1) THEN MP_TAC(ISPECL [`a:real^N`; `b:real^N`] ENDS_IN_SEGMENT) THEN MP_TAC(ISPECL [`(f:real^N->real^1) a`; `(f:real^1->real^1) b`] ENDS_IN_SEGMENT) THEN ASM SET_TAC[]);;
let CONTINUOUS_IVT_LOCAL_EXTREMUM = 
prove (`!f:real^N->real^1 a b. f continuous_on segment[a,b] /\ ~(a = b) /\ f(a) = f(b) ==> ?z. z IN segment(a,b) /\ ((!w. w IN segment[a,b] ==> drop(f w) <= drop(f z)) \/ (!w. w IN segment[a,b] ==> drop(f z) <= drop(f w)))`,
REPEAT STRIP_TAC THEN MAP_EVERY (MP_TAC o ISPECL [`drop o (f:real^N->real^1)`; `segment[a:real^N,b]`]) [CONTINUOUS_ATTAINS_SUP; CONTINUOUS_ATTAINS_INF] THEN ASM_REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX] THEN REWRITE_TAC[COMPACT_SEGMENT; SEGMENT_EQ_EMPTY] THEN DISCH_THEN(X_CHOOSE_THEN `d:real^N` STRIP_ASSUME_TAC) THEN ASM_CASES_TAC `(d:real^N) IN segment(a,b)` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `c:real^N` STRIP_ASSUME_TAC) THEN ASM_CASES_TAC `(c:real^N) IN segment(a,b)` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN EXISTS_TAC `midpoint(a:real^N,b)` THEN MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL [ASM_REWRITE_TAC[MIDPOINT_IN_SEGMENT]; DISCH_TAC] THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CONJUNCT2 segment]) THEN REPEAT(FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE (RAND_CONV o RAND_CONV) [segment])) THEN ASM_REWRITE_TAC[IN_DIFF; IN_INSERT; NOT_IN_EMPTY] THEN REPEAT(DISCH_THEN(DISJ_CASES_THEN SUBST_ALL_TAC)) THEN FIRST_X_ASSUM SUBST_ALL_TAC THEN ASM_MESON_TAC[REAL_LE_ANTISYM; DROP_EQ]);;
let FRONTIER_UNIONS_SUBSET_CLOSURE = 
prove (`!f:(real^N->bool)->bool. frontier(UNIONS f) SUBSET closure(UNIONS {frontier t | t IN f})`,
GEN_TAC THEN GEN_REWRITE_TAC LAND_CONV [frontier] THEN REWRITE_TAC[SUBSET; IN_DIFF; CLOSURE_APPROACHABLE] THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[EXISTS_IN_UNIONS; EXISTS_IN_GSPEC; RIGHT_EXISTS_AND_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN ASM_CASES_TAC `(t:real^N->bool) IN f` THEN ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `(x:real^N) IN t` THENL [DISCH_THEN(K ALL_TAC) THEN EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[frontier; DIST_REFL; IN_DIFF] THEN ASM_SIMP_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN FIRST_X_ASSUM(MP_TAC o check (is_neg o concl)) THEN SPEC_TAC(`x:real^N`,`z:real^N`) THEN REWRITE_TAC[CONTRAPOS_THM; GSYM SUBSET] THEN MATCH_MP_TAC SUBSET_INTERIOR THEN ASM SET_TAC[]; DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN MP_TAC(ISPECL [`segment[x:real^N,y]`; `t:real^N->bool`] CONNECTED_INTER_FRONTIER) THEN SIMP_TAC[CONNECTED_SEGMENT; GSYM MEMBER_NOT_EMPTY; IN_INTER; IN_DIFF] THEN ANTS_TAC THENL [ASM_MESON_TAC[ENDS_IN_SEGMENT]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `z:real^N` THEN ASM_MESON_TAC[DIST_IN_CLOSED_SEGMENT; DIST_SYM; REAL_LET_TRANS]]);;
let CLOSURE_CONVEX_INTER_AFFINE = 
prove (`!s t:real^N->bool. convex s /\ affine t /\ ~(relative_interior s INTER t = {}) ==> closure(s INTER t) = closure(s) INTER t`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET_INTER] THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC SUBSET_CLOSURE THEN SET_TAC[]; TRANS_TAC SUBSET_TRANS `closure t:real^N->bool` THEN SIMP_TAC[SUBSET_CLOSURE; INTER_SUBSET] THEN ASM_SIMP_TAC[CLOSURE_CLOSED; CLOSED_AFFINE; SUBSET_REFL]; ALL_TAC] THEN FIRST_X_ASSUM(X_CHOOSE_THEN `a:real^N` MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN GEOM_ORIGIN_TAC `a:real^N` THEN REPEAT GEN_TAC THEN REWRITE_TAC[IN_INTER] THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_SIMP_TAC[AFFINE_EQ_SUBSPACE] THEN STRIP_TAC THEN FIRST_ASSUM(ASSUME_TAC o MATCH_MP(REWRITE_RULE[SUBSET] RELATIVE_INTERIOR_SUBSET)) THEN REWRITE_TAC[SUBSET; IN_INTER] THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN ASM_CASES_TAC `x:real^N = vec 0` THENL [MATCH_MP_TAC(REWRITE_RULE[SUBSET] CLOSURE_SUBSET) THEN ASM_REWRITE_TAC[IN_INTER]; ALL_TAC] THEN SUBGOAL_THEN `x IN closure(segment(vec 0:real^N,x))` MP_TAC THENL [ASM_REWRITE_TAC[CLOSURE_SEGMENT; ENDS_IN_SEGMENT]; ALL_TAC] THEN MATCH_MP_TAC(SET_RULE `s SUBSET t ==> x IN s ==> x IN t`) THEN MATCH_MP_TAC SUBSET_CLOSURE THEN REWRITE_TAC[SUBSET_INTER] THEN CONJ_TAC THENL [TRANS_TAC SUBSET_TRANS `relative_interior s:real^N->bool` THEN REWRITE_TAC[RELATIVE_INTERIOR_SUBSET] THEN MATCH_MP_TAC IN_RELATIVE_INTERIOR_CLOSURE_CONVEX_SEGMENT THEN ASM_REWRITE_TAC[]; ASM_SIMP_TAC[SUBSET; IN_SEGMENT; VECTOR_MUL_RZERO; VECTOR_ADD_LID; SUBSPACE_MUL; LEFT_IMP_EXISTS_THM]]);;
let RELATIVE_FRONTIER_CONVEX_INTER_AFFINE = 
prove (`!s t:real^N->bool. convex s /\ affine t /\ ~(interior s INTER t = {}) ==> relative_frontier(s INTER t) = frontier s INTER t`,
SIMP_TAC[relative_frontier; RELATIVE_INTERIOR_CONVEX_INTER_AFFINE; frontier] THEN REPEAT STRIP_TAC THEN SUBGOAL_THEN `~(relative_interior s INTER t:real^N->bool = {})` ASSUME_TAC THENL [MP_TAC(ISPEC `s:real^N->bool` INTERIOR_SUBSET_RELATIVE_INTERIOR) THEN ASM SET_TAC[]; ASM_SIMP_TAC[CLOSURE_CONVEX_INTER_AFFINE] THEN SET_TAC[]]);;
let CONNECTED_COMPONENT_1_GEN = 
prove (`!s a b:real^N. dimindex(:N) = 1 ==> (connected_component s a b <=> segment[a,b] SUBSET s)`,
let CONNECTED_COMPONENT_1 = 
prove (`!s a b:real^1. connected_component s a b <=> segment[a,b] SUBSET s`,
SIMP_TAC[CONNECTED_COMPONENT_1_GEN; DIMINDEX_1]);;
(* ------------------------------------------------------------------------- *) (* An injective function into R is a homeomorphism and so an open map. *) (* ------------------------------------------------------------------------- *)
let INJECTIVE_INTO_1D_EQ_HOMEOMORPHISM = 
prove (`!f:real^N->real^1 s. f continuous_on s /\ path_connected s ==> ((!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) <=> ?g. homeomorphism (s,IMAGE f s) (f,g))`,
REPEAT STRIP_TAC THEN EQ_TAC THENL [REWRITE_TAC[INJECTIVE_ON_LEFT_INVERSE]; REWRITE_TAC[homeomorphism] THEN MESON_TAC[]] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `g:real^1->real^N` THEN STRIP_TAC THEN ASM_SIMP_TAC[homeomorphism; FORALL_IN_IMAGE] THEN CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `is_interval (IMAGE (f:real^N->real^1) s)` ASSUME_TAC THENL [REWRITE_TAC[IS_INTERVAL_PATH_CONNECTED_1] THEN ASM_MESON_TAC[PATH_CONNECTED_CONTINUOUS_IMAGE]; ALL_TAC] THEN REWRITE_TAC[continuous_on; IMP_CONJ; FORALL_IN_IMAGE] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN ABBREV_TAC `y = (f:real^N->real^1) x` THEN ABBREV_TAC `t = IMAGE (f:real^N->real^1) s` THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN SUBGOAL_THEN `?a b d. a IN s /\ b IN s /\ &0 < d /\ ball(y,d) INTER t SUBSET segment[(f:real^N->real^1) a,f b]` STRIP_ASSUME_TAC THENL [MP_TAC(ISPECL [`t:real^1->bool`; `y:real^1`] INTERVAL_CONTAINS_COMPACT_NEIGHBOURHOOD) THEN ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN ASM_SIMP_TAC[INTERVAL_SUBSET_IS_INTERVAL] THEN REWRITE_TAC[SET_RULE `P /\ y IN s /\ (s = {} \/ a IN t /\ b IN t) /\ R <=> a IN t /\ b IN t /\ P /\ y IN s /\ R`] THEN REWRITE_TAC[RIGHT_EXISTS_AND_THM] THEN EXPAND_TAC "t" THEN REWRITE_TAC[EXISTS_IN_IMAGE] THEN REWRITE_TAC[SEGMENT_1; IN_INTERVAL_1] THEN MESON_TAC[REAL_LE_TRANS]; FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [path_connected]) THEN DISCH_THEN(MP_TAC o SPECL [`a:real^N`; `b:real^N`]) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `p:real^1->real^N` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `(g:real^1->real^N) continuous_on segment[(f:real^N->real^1) a,f b]` MP_TAC THENL [MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `IMAGE (f:real^N->real^1) (path_image p)` THEN CONJ_TAC THENL [MATCH_MP_TAC CONTINUOUS_ON_INVERSE THEN ASM_SIMP_TAC[COMPACT_PATH_IMAGE] THEN CONJ_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; ASM SET_TAC[]]; SUBGOAL_THEN `convex(IMAGE (f:real^N->real^1) (path_image p))` MP_TAC THENL [REWRITE_TAC[GSYM IS_INTERVAL_CONVEX_1; IS_INTERVAL_CONNECTED_1] THEN MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN ASM_SIMP_TAC[CONNECTED_PATH_IMAGE] THEN ASM_MESON_TAC[CONTINUOUS_ON_SUBSET]; REWRITE_TAC[CONVEX_CONTAINS_SEGMENT] THEN DISCH_THEN MATCH_MP_TAC THEN CONJ_TAC THEN MATCH_MP_TAC FUN_IN_IMAGE THEN ASM_MESON_TAC[PATHSTART_IN_PATH_IMAGE; PATHFINISH_IN_PATH_IMAGE]]]; REWRITE_TAC[continuous_on] THEN DISCH_THEN(MP_TAC o SPEC `y:real^1`) THEN ANTS_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN ASM_REWRITE_TAC[IN_INTER; CENTRE_IN_BALL] THEN ASM SET_TAC[]; ALL_TAC] THEN DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `k:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `min d k` THEN ASM_REWRITE_TAC[REAL_LT_MIN] THEN X_GEN_TAC `x':real^N` THEN REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN ASM_REWRITE_TAC[IN_INTER; IN_BALL] THEN ONCE_REWRITE_TAC[DIST_SYM] THEN ASM SET_TAC[]]]);;
let INJECTIVE_INTO_1D_IMP_OPEN_MAP = 
prove (`!f:real^N->real^1 s t. f continuous_on s /\ path_connected s /\ (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\ open_in (subtopology euclidean s) t ==> open_in (subtopology euclidean (IMAGE f s)) (IMAGE f t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC HOMEOMORPHISM_IMP_OPEN_MAP THEN ASM_MESON_TAC[INJECTIVE_INTO_1D_EQ_HOMEOMORPHISM]);;
(* ------------------------------------------------------------------------- *) (* Injective function on an interval is strictly increasing or decreasing. *) (* ------------------------------------------------------------------------- *)
let CONTINUOUS_INJECTIVE_IFF_MONOTONIC = 
prove (`!f:real^1->real^1 s. f continuous_on s /\ is_interval s ==> ((!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) <=> (!x y. x IN s /\ y IN s /\ drop x < drop y ==> drop(f x) < drop(f y)) \/ (!x y. x IN s /\ y IN s /\ drop x < drop y ==> drop(f y) < drop(f x)))`,
let lemma = prove
   (`!s f:real^1->real^1.
        f continuous_on s /\ is_interval s /\
        (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
        ==> !u v w. u IN s /\ v IN s /\ w IN s /\
                    drop u < drop v /\ drop v < drop w /\
                    drop(f u) <= drop(f v) /\ drop(f w) <= drop(f v) ==> F`,
    REWRITE_TAC[IS_INTERVAL_CONVEX_1; CONVEX_CONTAINS_SEGMENT] THEN
    REPEAT STRIP_TAC THEN
    MP_TAC(ISPECL [`f:real^1->real^1`; `u:real^1`; `w:real^1`]
        CONTINUOUS_INJECTIVE_IMAGE_SEGMENT_1) THEN
    ANTS_TAC THENL [ASM_MESON_TAC[CONTINUOUS_ON_SUBSET; SUBSET]; ALL_TAC] THEN
    REWRITE_TAC[EXTENSION] THEN
    DISCH_THEN(MP_TAC o SPEC `(f:real^1->real^1) v`) THEN
    MATCH_MP_TAC(TAUT `p /\ ~q ==> (p <=> q) ==> F`) THEN CONJ_TAC THENL
     [MATCH_MP_TAC FUN_IN_IMAGE THEN ASM_REWRITE_TAC[SEGMENT_1] THEN
      COND_CASES_TAC THENL
       [ASM_SIMP_TAC[IN_INTERVAL_1; REAL_LT_IMP_LE]; ASM_REAL_ARITH_TAC];
      REWRITE_TAC[SEGMENT_1] THEN COND_CASES_TAC THEN
      ASM_REWRITE_TAC[IN_INTERVAL_1] THEN DISCH_TAC THENL
       [SUBGOAL_THEN `drop(f(w:real^1)) = drop(f v)` ASSUME_TAC THENL
         [ASM_REAL_ARITH_TAC; ASM_MESON_TAC[DROP_EQ; REAL_LT_REFL]];
        SUBGOAL_THEN `drop(f(u:real^1)) = drop(f v)` ASSUME_TAC THENL
         [ASM_REAL_ARITH_TAC; ASM_MESON_TAC[DROP_EQ; REAL_LT_REFL]]]])
  and tac s1 s2 =
   let [l1;l2] = map (map (fun x -> mk_var(x,`:real^1`)) o explode) [s1;s2] in
   REPEAT(FIRST_X_ASSUM(fun th ->
     MP_TAC(ISPECL l1 th) THEN MP_TAC(ISPECL l2 th))) THEN
   ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC in
  REPEAT STRIP_TAC THEN EQ_TAC THENL
   [ALL_TAC;
    REWRITE_TAC[GSYM DROP_EQ] THEN
    MESON_TAC[REAL_LT_TOTAL; REAL_LT_REFL]] THEN
  DISCH_TAC THEN MATCH_MP_TAC(MESON[]
   `(!a b c d. ~(~P a b /\ ~Q c d)) ==> (!x y. P x y) \/ (!x y. Q x y)`) THEN
  MAP_EVERY X_GEN_TAC [`a:real^1`; `b:real^1`; `c:real^1`; `d:real^1`] THEN
  REWRITE_TAC[NOT_IMP; REAL_NOT_LT] THEN STRIP_TAC THEN
  REPEAT
   (FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [REAL_LE_LT]) THEN
    REWRITE_TAC[DROP_EQ] THEN STRIP_TAC THENL
     [ALL_TAC; ASM_MESON_TAC[REAL_LT_REFL]]) THEN
  MP_TAC(ISPEC `s:real^1->bool` lemma) THEN ASM_REWRITE_TAC[] THEN
  DISCH_THEN(fun th ->
   MP_TAC(SPEC `(--) o (f:real^1->real^1)` th) THEN
   MP_TAC(SPEC `f:real^1->real^1` th)) THEN
  ASM_REWRITE_TAC[o_THM; VECTOR_ARITH `--x:real^N = --y <=> x = y`] THEN
  DISCH_TAC THEN REWRITE_TAC[NOT_IMP; DROP_NEG; REAL_LE_NEG2] THEN
  CONJ_TAC THENL
   [ASM_MESON_TAC[CONTINUOUS_ON_COMPOSE;LINEAR_CONTINUOUS_ON; LINEAR_NEGATION];
    DISCH_TAC] THEN
  ASM_CASES_TAC `drop d <= drop a` THENL [tac "cab" "cdb";
ALL_TAC] THEN ASM_CASES_TAC `drop b <= drop c` THENL [tac "abd" "acd"; ALL_TAC] THEN ASM_CASES_TAC `c:real^1 = a /\ d:real^1 = b` THENL [ASM_MESON_TAC[REAL_LT_ANTISYM]; ALL_TAC] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[] `~(c = a /\ d = b) ==> (c = a ==> d = b) /\ (d = b ==> c = a) /\ (~(c = a) /\ ~(d = b) ==> F) ==> F`)) THEN REPEAT CONJ_TAC THENL [DISCH_THEN SUBST_ALL_TAC THEN SIMP_TAC[GSYM DROP_EQ] THEN tac "adb" "abd"; DISCH_THEN SUBST_ALL_TAC THEN SIMP_TAC[GSYM DROP_EQ] THEN tac "acb" "cab"; REWRITE_TAC[GSYM DROP_EQ] THEN STRIP_TAC] THEN ASM_CASES_TAC `drop a <= drop c` THENL [tac "acb" "acd"; tac "cab" "cad"]);; (* ------------------------------------------------------------------------- *) (* Some uncountability results for relevant sets. *) (* ------------------------------------------------------------------------- *)
let CARD_EQ_SEGMENT = 
prove (`(!a b:real^N. ~(a = b) ==> segment[a,b] =_c (:real)) /\ (!a b:real^N. ~(a = b) ==> segment(a,b) =_c (:real))`,
REPEAT STRIP_TAC THEN ASM_SIMP_TAC[SEGMENT_IMAGE_INTERVAL] THENL [TRANS_TAC CARD_EQ_TRANS `interval[vec 0:real^1,vec 1]`; TRANS_TAC CARD_EQ_TRANS `interval(vec 0:real^1,vec 1)`] THEN SIMP_TAC[CARD_EQ_INTERVAL; UNIT_INTERVAL_NONEMPTY] THEN MATCH_MP_TAC CARD_EQ_IMAGE THEN ASM_REWRITE_TAC[VECTOR_MUL_EQ_0; VECTOR_SUB_EQ; VECTOR_ARITH `(&1 - x) % a + x % b:real^N = (&1 - y) % a + y % b <=> (x - y) % (a - b) = vec 0`] THEN SIMP_TAC[REAL_SUB_0; DROP_EQ]);;
let UNCOUNTABLE_SEGMENT = 
prove (`(!a b:real^N. ~(a = b) ==> ~COUNTABLE(segment[a,b])) /\ (!a b:real^N. ~(a = b) ==> ~COUNTABLE(segment(a,b)))`,
let CARD_EQ_PATH_CONNECTED = 
prove (`!s a b:real^N. path_connected s /\ a IN s /\ b IN s /\ ~(a = b) ==> s =_c (:real)`,
let UNCOUNTABLE_PATH_CONNECTED = 
prove (`!s a b:real^N. path_connected s /\ a IN s /\ b IN s /\ ~(a = b) ==> ~COUNTABLE s`,
REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CARD_EQ_REAL_IMP_UNCOUNTABLE THEN MATCH_MP_TAC CARD_EQ_PATH_CONNECTED THEN ASM_MESON_TAC[]);;
let CARD_EQ_CONVEX = 
prove (`!s a b:real^N. convex s /\ a IN s /\ b IN s /\ ~(a = b) ==> s =_c (:real)`,
let UNCOUNTABLE_CONVEX = 
prove (`!s a b:real^N. convex s /\ a IN s /\ b IN s /\ ~(a = b) ==> ~COUNTABLE s`,
REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC CARD_EQ_REAL_IMP_UNCOUNTABLE THEN MATCH_MP_TAC CARD_EQ_CONVEX THEN ASM_MESON_TAC[]);;
let CARD_EQ_NONEMPTY_INTERIOR = 
prove (`!s:real^N->bool. ~(interior s = {}) ==> s =_c (:real)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN SIMP_TAC[CARD_LE_UNIV; CARD_EQ_IMP_LE; CARD_EQ_EUCLIDEAN]; TRANS_TAC CARD_LE_TRANS `interior(s:real^N->bool)` THEN SIMP_TAC[CARD_LE_SUBSET; INTERIOR_SUBSET] THEN MATCH_MP_TAC(ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE) THEN MATCH_MP_TAC CARD_EQ_OPEN THEN ASM_REWRITE_TAC[OPEN_INTERIOR]]);;
let UNCOUNTABLE_NONEMPTY_INTERIOR = 
prove (`!s:real^N->bool. ~(interior s = {}) ==> ~(COUNTABLE s)`,
let COUNTABLE_EMPTY_INTERIOR = 
prove (`!s:real^N->bool. COUNTABLE s ==> interior s = {}`,
let FINITE_EMPTY_INTERIOR = 
prove (`!s:real^N->bool. FINITE s ==> interior s = {}`,
let [CONNECTED_FINITE_IFF_SING; CONNECTED_FINITE_IFF_COUNTABLE; CONNECTED_INFINITE_IFF_CARD_EQ] = (CONJUNCTS o prove) (`(!s:real^N->bool. connected s ==> (FINITE s <=> s = {} \/ ?a. s = {a})) /\ (!s:real^N->bool. connected s ==> (FINITE s <=> COUNTABLE s)) /\ (!s:real^N->bool. connected s ==> (INFINITE s <=> s =_c (:real)))`, REWRITE_TAC[AND_FORALL_THM] THEN GEN_TAC THEN ASM_CASES_TAC `connected(s:real^N->bool)` THEN ASM_REWRITE_TAC[INFINITE] THEN MATCH_MP_TAC(TAUT `(f ==> c) /\ (r ==> ~c) /\ (s ==> f) /\ (~s ==> r) ==> (f <=> s) /\ (f <=> c) /\ (~f <=> r)`) THEN REWRITE_TAC[FINITE_IMP_COUNTABLE] THEN REPEAT CONJ_TAC THEN STRIP_TAC THEN ASM_SIMP_TAC[CARD_EQ_REAL_IMP_UNCOUNTABLE; FINITE_INSERT; FINITE_EMPTY] THEN MATCH_MP_TAC CARD_EQ_CONNECTED THEN ASM SET_TAC[]);;
let CLOSED_AS_FRONTIER_OF_SUBSET = 
prove (`!s:real^N->bool. closed s <=> ?t. t SUBSET s /\ s = frontier t`,
GEN_TAC THEN EQ_TAC THENL [ALL_TAC; MESON_TAC[FRONTIER_CLOSED]] THEN DISCH_TAC THEN MP_TAC(ISPEC `s:real^N->bool` SEPARABLE) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN SIMP_TAC[frontier] THEN STRIP_TAC THEN MATCH_MP_TAC(SET_RULE `s SUBSET c /\ c SUBSET s /\ i = {} ==> s = c DIFF i`) THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ASM_MESON_TAC[SUBSET_CLOSURE; CLOSURE_CLOSED]; ASM_MESON_TAC[UNCOUNTABLE_NONEMPTY_INTERIOR]]);;
let CLOSED_AS_FRONTIER = 
prove (`!s:real^N->bool. closed s <=> ?t. s = frontier t`,
GEN_TAC THEN EQ_TAC THENL [MESON_TAC[CLOSED_AS_FRONTIER_OF_SUBSET]; MESON_TAC[FRONTIER_CLOSED]]);;
let CARD_EQ_CLOSED = 
prove (`!s:real^N->bool. closed s ==> s <=_c (:num) \/ s =_c (:real)`,
let slemma = prove
   (`!s:real^N->bool.
          ~COUNTABLE s
          ==> ?x y. ~(x = y) /\ x IN s /\ y IN s /\
                    x condensation_point_of s /\
                    y condensation_point_of s`,
    REPEAT STRIP_TAC THEN
    FIRST_ASSUM(MP_TAC o MATCH_MP CARD_EQ_CONDENSATION_POINTS_IN_SET) THEN
    DISCH_THEN(MP_TAC o MATCH_MP CARD_INFINITE_CONG) THEN
    REWRITE_TAC[INFINITE] THEN
    MATCH_MP_TAC(TAUT `q /\ (p ==> s) ==> (p <=> q) ==> s`) THEN
    CONJ_TAC THENL [ASM_MESON_TAC[FINITE_IMP_COUNTABLE]; ALL_TAC] THEN
    DISCH_TAC THEN
    MP_TAC(ISPECL [`2`; `{x:real^N | x IN s /\ x condensation_point_of s}`]
          CHOOSE_SUBSET_STRONG) THEN
    ASM_REWRITE_TAC[HAS_SIZE_CONV `s HAS_SIZE 2`; RIGHT_AND_EXISTS_THM] THEN
    DISCH_THEN(CHOOSE_THEN MP_TAC) THEN REWRITE_TAC[SUBSET; IN_ELIM_THM] THEN
    REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN
    STRIP_TAC THEN FIRST_X_ASSUM SUBST_ALL_TAC THEN
    RULE_ASSUM_TAC(REWRITE_RULE[FORALL_IN_INSERT; NOT_IN_EMPTY]) THEN
    ASM_REWRITE_TAC[]) in
  GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[GSYM COUNTABLE_ALT] THEN
  ASM_CASES_TAC `COUNTABLE(s:real^N->bool)` THEN ASM_REWRITE_TAC[] THEN
  SUBGOAL_THEN
   `!n t:real^N->bool.
        closed t /\ ~COUNTABLE t
        ==> ?l r. (compact l /\ ~COUNTABLE l) /\ (compact r /\ ~COUNTABLE r) /\
                  l INTER r = {} /\ l SUBSET t /\ r SUBSET t /\
                  diameter l <= inv(&2 pow n) /\
                  diameter r <= inv(&2 pow n)`
  MP_TAC THENL
   [REPEAT GEN_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC
     (MP_TAC o MATCH_MP slemma)) THEN
    REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
    MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN
    MAP_EVERY EXISTS_TAC
     [`t INTER cball(a:real^N,min (inv(&2 pow (SUC n))) (dist(a,b) / &3))`;
     `t INTER cball(b:real^N,min (inv(&2 pow (SUC n))) (dist(a,b) / &3))`] THEN
    ASM_SIMP_TAC[CLOSED_INTER_COMPACT; COMPACT_CBALL] THEN
    REPEAT CONJ_TAC THENL
     [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I
       [CONDENSATION_POINT_INFINITE_CBALL]) THEN
      REWRITE_TAC[REAL_LT_MIN; REAL_LT_INV_EQ; REAL_LT_POW2] THEN
      UNDISCH_TAC `~(a:real^N = b)` THEN CONV_TAC NORM_ARITH;
      FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I
       [CONDENSATION_POINT_INFINITE_CBALL]) THEN
      REWRITE_TAC[REAL_LT_MIN; REAL_LT_INV_EQ; REAL_LT_POW2] THEN
      UNDISCH_TAC `~(a:real^N = b)` THEN CONV_TAC NORM_ARITH;
      MATCH_MP_TAC(SET_RULE
       `(!x. ~(x IN t /\ x IN u)) ==> (s INTER t) INTER (s INTER u) = {}`) THEN
      REWRITE_TAC[IN_CBALL; REAL_LE_MIN] THEN
      UNDISCH_TAC `~(a:real^N = b)` THEN CONV_TAC NORM_ARITH;
      SET_TAC[];
      SET_TAC[];
      MATCH_MP_TAC DIAMETER_LE THEN
      SIMP_TAC[REAL_LE_INV_EQ; REAL_LT_IMP_LE; REAL_LT_POW2] THEN
      REWRITE_TAC[IN_INTER; IN_CBALL; REAL_LE_MIN; real_pow; REAL_INV_MUL] THEN
      CONV_TAC NORM_ARITH;
      MATCH_MP_TAC DIAMETER_LE THEN
      SIMP_TAC[REAL_LE_INV_EQ; REAL_LT_IMP_LE; REAL_LT_POW2] THEN
      REWRITE_TAC[IN_INTER; IN_CBALL; REAL_LE_MIN; real_pow; REAL_INV_MUL] THEN
      CONV_TAC NORM_ARITH];
    REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
    MAP_EVERY X_GEN_TAC
     [`l:num->(real^N->bool)->(real^N->bool)`;
      `r:num->(real^N->bool)->(real^N->bool)`] THEN
    DISCH_TAC THEN
    SUBGOAL_THEN
     `!b. ?x:num->real^N->bool.
          (x 0 = s) /\ (!n. x(SUC n) = if b(n) then r n (x n) else l n (x n))`
    MP_TAC THENL
     [GEN_TAC THEN
      W(ACCEPT_TAC o prove_recursive_functions_exist num_RECURSION o
        snd o dest_exists o snd);
      REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM; FORALL_AND_THM]] THEN
    X_GEN_TAC `x:(num->bool)->num->real^N->bool` THEN STRIP_TAC THEN
    REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL
     [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN
      SIMP_TAC[CARD_LE_UNIV; CARD_EQ_EUCLIDEAN; CARD_EQ_IMP_LE];
      TRANS_TAC CARD_LE_TRANS `(:num->bool)` THEN
      SIMP_TAC[CARD_EQ_REAL; CARD_EQ_IMP_LE]] THEN
    REWRITE_TAC[le_c; IN_UNIV] THEN
    SUBGOAL_THEN
     `!b n. closed((x:(num->bool)->num->real^N->bool) b n) /\
            ~COUNTABLE(x b n)`
    MP_TAC THENL
     [GEN_TAC THEN INDUCT_TAC THEN ASM_SIMP_TAC[] THEN
      COND_CASES_TAC THEN ASM_SIMP_TAC[COMPACT_IMP_CLOSED];
      REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC] THEN
    MP_TAC(GEN `b:num->bool` (ISPEC `(x:(num->bool)->num->real^N->bool) b`
          DECREASING_CLOSED_NEST_SING)) THEN
    DISCH_THEN(MP_TAC o MATCH_MP MONO_FORALL) THEN ANTS_TAC THENL
     [ASM_SIMP_TAC[FORALL_AND_THM] THEN REPEAT CONJ_TAC THENL
       [ASM_MESON_TAC[COUNTABLE_EMPTY];
        GEN_TAC THEN MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN
        REWRITE_TAC[SUBSET_REFL] THEN ASM SET_TAC[];
        MAP_EVERY X_GEN_TAC [`b:num->bool`; `e:real`] THEN DISCH_TAC THEN
        MP_TAC(ISPECL [`inv(&2)`; `e:real`] REAL_ARCH_POW_INV) THEN
        ASM_REWRITE_TAC[REAL_POW_INV] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
        DISCH_THEN(X_CHOOSE_TAC `m:num`) THEN
        EXISTS_TAC `SUC m` THEN ASM_SIMP_TAC[] THEN
        REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
        DISCH_THEN(MP_TAC o MATCH_MP
         (REWRITE_RULE[TAUT `p /\ q /\ r ==> s <=> q /\ r ==> p ==> s`]
          DIAMETER_BOUNDED_BOUND)) THEN
        ASM_SIMP_TAC[COMPACT_IMP_BOUNDED] THEN
        UNDISCH_TAC `inv(&2 pow m) < e` THEN MATCH_MP_TAC(NORM_ARITH
         `d <= i ==> i < e ==> norm(x - y) <= d ==> dist(x:real^N,y) < e`) THEN
        ASM_SIMP_TAC[]];
      ALL_TAC] THEN
    REWRITE_TAC[SKOLEM_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN
    X_GEN_TAC `f:(num->bool)->real^N` THEN STRIP_TAC THEN CONJ_TAC THENL
     [X_GEN_TAC `b:num->bool` THEN
      REWRITE_TAC[SET_RULE `x IN s <=> {x} SUBSET s`] THEN
      FIRST_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [GSYM th]) THEN
      REWRITE_TAC[SUBSET; INTERS_GSPEC; IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN
      ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
      SIMP_TAC[FORALL_UNWIND_THM2] THEN GEN_TAC THEN ASM SET_TAC[];
      MAP_EVERY X_GEN_TAC [`b:num->bool`; `c:num->bool`] THEN
      ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
      GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [FUN_EQ_THM] THEN
      REWRITE_TAC[NOT_FORALL_THM] THEN ONCE_REWRITE_TAC[num_WOP] THEN
      SIMP_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `k:num` STRIP_ASSUME_TAC) THEN
      MATCH_MP_TAC(SET_RULE
       `!f g. INTERS f = {a} /\ INTERS g = {b} /\
              (?s t. s IN f /\ t IN g /\ s INTER t = {})
              ==> ~(a = b)`) THEN
      EXISTS_TAC `{t | ?n. t = (x:(num->bool)->num->real^N->bool) b n}` THEN
      EXISTS_TAC `{t | ?n. t = (x:(num->bool)->num->real^N->bool) c n}` THEN
      ASM_REWRITE_TAC[IN_ELIM_THM] THEN
      EXISTS_TAC `(x:(num->bool)->num->real^N->bool) b (SUC k)` THEN
      EXISTS_TAC `(x:(num->bool)->num->real^N->bool) c (SUC k)` THEN
      REPEAT(CONJ_TAC THENL [MESON_TAC[]; ALL_TAC]) THEN ASM_SIMP_TAC[] THEN
      SUBGOAL_THEN
       `!i. i <= k ==> (x:(num->bool)->num->real^N->bool) b i = x c i`
      MP_TAC THENL
       [INDUCT_TAC THEN ASM_SIMP_TAC[LE_SUC_LT; LT_IMP_LE];
        DISCH_THEN(MP_TAC o SPEC `k:num`)] THEN
      REWRITE_TAC[LE_REFL] THEN DISCH_THEN SUBST1_TAC THEN
      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I
       [TAUT `~(p <=> q) <=> (q <=> ~p)`]) THEN
      REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
      ASM_MESON_TAC[INTER_COMM]]]);;
let CONDENSATION_POINTS_EQ_EMPTY,CARD_EQ_CONDENSATION_POINTS = (CONJ_PAIR o prove) (`(!s:real^N->bool. {x | x condensation_point_of s} = {} <=> COUNTABLE s) /\ (!s:real^N->bool. {x | x condensation_point_of s} =_c (:real) <=> ~(COUNTABLE s))`, REWRITE_TAC[AND_FORALL_THM] THEN GEN_TAC THEN MATCH_MP_TAC(TAUT `(r ==> p) /\ (~r ==> q) /\ (p ==> ~q) ==> (p <=> r) /\ (q <=> ~r)`) THEN REPEAT CONJ_TAC THENL [DISCH_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM; NOT_IN_EMPTY] THEN REWRITE_TAC[condensation_point_of] THEN ASM_MESON_TAC[COUNTABLE_SUBSET; INTER_SUBSET; IN_UNIV; OPEN_UNIV]; DISCH_TAC THEN MATCH_MP_TAC(REWRITE_RULE [TAUT `p ==> q \/ r <=> p /\ ~q ==> r`] CARD_EQ_CLOSED) THEN REWRITE_TAC[CLOSED_CONDENSATION_POINTS; GSYM COUNTABLE_ALT] THEN FIRST_ASSUM(MP_TAC o MATCH_MP CARD_EQ_CONDENSATION_POINTS_IN_SET) THEN DISCH_THEN(MP_TAC o MATCH_MP CARD_COUNTABLE_CONG) THEN ASM_REWRITE_TAC[CONTRAPOS_THM] THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] COUNTABLE_SUBSET) THEN SET_TAC[]; DISCH_THEN SUBST1_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CARD_FINITE_CONG) THEN REWRITE_TAC[FINITE_EMPTY; GSYM INFINITE; real_INFINITE]]);;
let UNCOUNTABLE_HAS_CONDENSATION_POINT = 
prove (`!s:real^N->bool. ~COUNTABLE s ==> ?x. x condensation_point_of s`,
REWRITE_TAC[GSYM CONDENSATION_POINTS_EQ_EMPTY] THEN SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Density of sets with small complement, including irrationals. *) (* ------------------------------------------------------------------------- *)
let COSMALL_APPROXIMATION = 
prove (`!s. ((:real) DIFF s) <_c (:real) ==> !x e. &0 < e ==> ?y. y IN s /\ abs(y - x) < e`,
let lemma = prove
   (`!s. ((:real^1) DIFF s) <_c (:real)
         ==> !x e. &0 < e ==> ?y. y IN s /\ norm(y - x) < e`,
    REPEAT STRIP_TAC THEN MATCH_MP_TAC(SET_RULE
      `~({x | P x} SUBSET UNIV DIFF s) ==> ?x. x IN s /\ P x`) THEN
    MP_TAC(ISPEC `ball(x:real^1,e)` CARD_EQ_OPEN) THEN
    ASM_REWRITE_TAC[OPEN_BALL; BALL_EQ_EMPTY; REAL_NOT_LE] THEN DISCH_TAC THEN
    DISCH_THEN(MP_TAC o MATCH_MP CARD_LE_SUBSET) THEN
    REWRITE_TAC[CARD_NOT_LE] THEN
    REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[DIST_SYM] dist); GSYM ball] THEN
    TRANS_TAC CARD_LTE_TRANS `(:real)` THEN
    ASM_SIMP_TAC[ONCE_REWRITE_RULE[CARD_EQ_SYM] CARD_EQ_IMP_LE]) in
  REWRITE_TAC[FORALL_DROP_IMAGE; FORALL_DROP; EXISTS_DROP] THEN
  REWRITE_TAC[GSYM IMAGE_DROP_UNIV; GSYM DROP_SUB; GSYM ABS_DROP] THEN
  REWRITE_TAC[DROP_IN_IMAGE_DROP] THEN REWRITE_TAC[GSYM FORALL_DROP] THEN
  SIMP_TAC[GSYM IMAGE_DIFF_INJ; DROP_EQ] THEN GEN_TAC THEN
  DISCH_TAC THEN MATCH_MP_TAC lemma THEN POP_ASSUM MP_TAC THEN
  MATCH_MP_TAC EQ_IMP THEN MATCH_MP_TAC CARD_LT_CONG THEN
  REWRITE_TAC[IMAGE_DROP_UNIV; CARD_EQ_REFL] THEN
  MATCH_MP_TAC CARD_EQ_IMAGE THEN SIMP_TAC[DROP_EQ]);;
let COCOUNTABLE_APPROXIMATION = 
prove (`!s. COUNTABLE((:real) DIFF s) ==> !x e. &0 < e ==> ?y. y IN s /\ abs(y - x) < e`,
GEN_TAC THEN REWRITE_TAC[COUNTABLE; ge_c] THEN DISCH_TAC THEN MATCH_MP_TAC COSMALL_APPROXIMATION THEN TRANS_TAC CARD_LET_TRANS `(:num)` THEN ASM_REWRITE_TAC[] THEN TRANS_TAC CARD_LTE_TRANS `(:num->bool)` THEN SIMP_TAC[CANTOR_THM_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN REWRITE_TAC[CARD_EQ_REAL]);;
let IRRATIONAL_APPROXIMATION = 
prove (`!x e. &0 < e ==> ?y. ~(rational y) /\ abs(y - x) < e`,
REWRITE_TAC[SET_RULE `~rational y <=> y IN UNIV DIFF rational`] THEN MATCH_MP_TAC COCOUNTABLE_APPROXIMATION THEN REWRITE_TAC[SET_RULE `UNIV DIFF (UNIV DIFF s) = s`; COUNTABLE_RATIONAL]);;
let OPEN_SET_COSMALL_COORDINATES = 
prove (`!P. (!i. 1 <= i /\ i <= dimindex(:N) ==> (:real) DIFF {x | P i x} <_c (:real)) ==> !s:real^N->bool. open s /\ ~(s = {}) ==> ?x. x IN s /\ !i. 1 <= i /\ i <= dimindex(:N) ==> P i (x$i)`,
REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN DISCH_THEN(X_CHOOSE_THEN `a:real^N` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN DISCH_THEN(MP_TAC o SPEC `a:real^N`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `!i. 1 <= i /\ i <= dimindex(:N) ==> ?y:real. P i y /\ abs(y - (a:real^N)$i) < d / &(dimindex(:N))` MP_TAC THENL [X_GEN_TAC `i:num` THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `i:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o MATCH_MP COSMALL_APPROXIMATION) THEN REWRITE_TAC[IN_ELIM_THM] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; LE_1; DIMINDEX_GE_1]; REWRITE_TAC[LAMBDA_SKOLEM] THEN MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[] THEN FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN REWRITE_TAC[IN_CBALL; dist] THEN W(MP_TAC o PART_MATCH lhand NORM_LE_L1 o lhand o snd) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ_ALT] REAL_LE_TRANS) THEN MATCH_MP_TAC SUM_BOUND_GEN THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN REWRITE_TAC[VECTOR_SUB_COMPONENT; NUMSEG_EMPTY; NOT_LT; DIMINDEX_GE_1] THEN ONCE_REWRITE_TAC[REAL_ABS_SUB] THEN ASM_SIMP_TAC[REAL_LT_IMP_LE; CARD_NUMSEG_1]]);;
let OPEN_SET_COCOUNTABLE_COORDINATES = 
prove (`!P. (!i. 1 <= i /\ i <= dimindex(:N) ==> COUNTABLE((:real) DIFF {x | P i x})) ==> !s:real^N->bool. open s /\ ~(s = {}) ==> ?x. x IN s /\ !i. 1 <= i /\ i <= dimindex(:N) ==> P i (x$i)`,
GEN_TAC THEN DISCH_TAC THEN MATCH_MP_TAC OPEN_SET_COSMALL_COORDINATES THEN REPEAT STRIP_TAC THEN TRANS_TAC CARD_LET_TRANS `(:num)` THEN ASM_SIMP_TAC[GSYM COUNTABLE_ALT] THEN TRANS_TAC CARD_LTE_TRANS `(:num->bool)` THEN SIMP_TAC[CANTOR_THM_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN REWRITE_TAC[CARD_EQ_REAL]);;
let OPEN_SET_IRRATIONAL_COORDINATES = 
prove (`!s:real^N->bool. open s /\ ~(s = {}) ==> ?x. x IN s /\ !i. 1 <= i /\ i <= dimindex(:N) ==> ~rational(x$i)`,
MATCH_MP_TAC OPEN_SET_COCOUNTABLE_COORDINATES THEN REWRITE_TAC[SET_RULE `UNIV DIFF {x | ~P x} = P`; COUNTABLE_RATIONAL]);;
let CLOSURE_COSMALL_COORDINATES = 
prove (`!P. (!i. 1 <= i /\ i <= dimindex(:N) ==> (:real) DIFF {x | P i x} <_c (:real)) ==> closure {x | !i. 1 <= i /\ i <= dimindex (:N) ==> P i (x$i)} = (:real^N)`,
GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[CLOSURE_APPROACHABLE; IN_UNIV; EXTENSION; IN_ELIM_THM] THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `e:real`] THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_SET_COSMALL_COORDINATES) THEN DISCH_THEN(MP_TAC o SPEC `ball(x:real^N,e)`) THEN ASM_REWRITE_TAC[OPEN_BALL; BALL_EQ_EMPTY; REAL_NOT_LE; IN_BALL] THEN MESON_TAC[DIST_SYM]);;
let CLOSURE_COCOUNTABLE_COORDINATES = 
prove (`!P. (!i. 1 <= i /\ i <= dimindex(:N) ==> COUNTABLE((:real) DIFF {x | P i x})) ==> closure {x | !i. 1 <= i /\ i <= dimindex (:N) ==> P i (x$i)} = (:real^N)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSURE_COSMALL_COORDINATES THEN REPEAT STRIP_TAC THEN TRANS_TAC CARD_LET_TRANS `(:num)` THEN ASM_SIMP_TAC[GSYM COUNTABLE_ALT] THEN TRANS_TAC CARD_LTE_TRANS `(:num->bool)` THEN SIMP_TAC[CANTOR_THM_UNIV] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN REWRITE_TAC[CARD_EQ_REAL]);;
let CLOSURE_IRRATIONAL_COORDINATES = 
prove (`closure {x | !i. 1 <= i /\ i <= dimindex (:N) ==> ~rational(x$i)} = (:real^N)`,
MATCH_MP_TAC CLOSURE_COCOUNTABLE_COORDINATES THEN REWRITE_TAC[SET_RULE `UNIV DIFF {x | ~P x} = P`; COUNTABLE_RATIONAL]);;
(* ------------------------------------------------------------------------- *) (* Every path between distinct points contains an arc, and hence *) (* that path connection is equivalent to arcwise connection, for distinct *) (* points. The proof is based on Whyburn's "Topological Analysis". *) (* ------------------------------------------------------------------------- *)
let HOMEOMORPHIC_MONOTONE_IMAGE_INTERVAL = 
prove (`!f:real^1->real^N. f continuous_on interval[vec 0,vec 1] /\ (!y. connected {x | x IN interval[vec 0,vec 1] /\ f x = y}) /\ ~(f(vec 1) = f(vec 0)) ==> (IMAGE f (interval[vec 0,vec 1])) homeomorphic (interval[vec 0:real^1,vec 1])`,
let closure_dyadic_rationals_in_convex_set_pos_1 = prove
   (`!s. convex s /\ ~(interior s = {}) /\ (!x. x IN s ==> &0 <= drop x)
         ==> closure(s INTER { lift(&m / &2 pow n) |
                               m IN (:num) /\ n IN (:num)}) =
             closure s`,
    REPEAT STRIP_TAC THEN
    MP_TAC(ISPEC `s:real^1->bool` CLOSURE_DYADIC_RATIONALS_IN_CONVEX_SET) THEN
    ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN AP_TERM_TAC THEN
    MATCH_MP_TAC(SET_RULE
     `(!x. x IN t ==> x IN u) /\ (!x. x IN u ==> x IN s ==> x IN t)
      ==> s INTER t = s INTER u`) THEN
    REWRITE_TAC[FORALL_IN_GSPEC; IN_UNIV; DIMINDEX_1; FORALL_1] THEN
    REWRITE_TAC[IN_ELIM_THM; EXISTS_LIFT; GSYM drop; LIFT_DROP] THEN
    REWRITE_TAC[REAL_ARITH `x / y:real = inv y * x`; LIFT_CMUL] THEN
    CONJ_TAC THENL [MESON_TAC[INTEGER_CLOSED]; ALL_TAC] THEN
    MAP_EVERY X_GEN_TAC [`n:num`; `x:real^1`] THEN REPEAT DISCH_TAC THEN
    FIRST_X_ASSUM(MP_TAC o SPEC `inv(&2 pow n) % x:real^1`) THEN
    ASM_SIMP_TAC[DROP_CMUL; REAL_LE_MUL_EQ; REAL_LT_POW2; REAL_LT_INV_EQ] THEN
    ASM_MESON_TAC[INTEGER_POS; LIFT_DROP]) in
  let function_on_dyadic_rationals = prove
   (`!f:num->num->A.
          (!m n. f (2 * m) (n + 1) = f m n)
          ==> ?g. !m n. g(&m / &2 pow n) = f m n`,
    REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[EQ_SYM_EQ] THEN MP_TAC(ISPECL
     [`\(m,n). (f:num->num->A) m n`; `\(m,n). &m / &2 pow n`]
     FUNCTION_FACTORS_LEFT) THEN
    REWRITE_TAC[FORALL_PAIR_THM; FUN_EQ_THM; o_THM] THEN
    DISCH_THEN (SUBST1_TAC o SYM) THEN
    ONCE_REWRITE_TAC[MESON[]
      `(!a b c d. P a b c d) <=> (!b d a c. P a b c d)`] THEN
    MATCH_MP_TAC WLOG_LE THEN REPEAT CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
    SIMP_TAC[REAL_FIELD `~(y = &0) /\ ~(y' = &0)
                         ==> (x / y = x' / y' <=> y' / y * x = x')`;
       REAL_POW_EQ_0; REAL_OF_NUM_EQ; REAL_DIV_POW2; ARITH_EQ] THEN
    SIMP_TAC[LE_EXISTS; LEFT_IMP_EXISTS_THM] THEN
    SIMP_TAC[ADD_SUB2; REAL_OF_NUM_MUL; REAL_OF_NUM_EQ; REAL_OF_NUM_POW] THEN
    REWRITE_TAC[MESON[]
     `(!n n' d. n' = f d n ==> !m m'. g d m = m' ==> P m m' n d) <=>
      (!d m n. P m (g d m) n d)`] THEN
    INDUCT_TAC THEN SIMP_TAC[EXP; MULT_CLAUSES; ADD_CLAUSES] THEN
    REWRITE_TAC[GSYM MULT_ASSOC; ADD1] THEN ASM_MESON_TAC[]) in
  let recursion_on_dyadic_rationals = prove
   (`!b:num->A l r.
          ?f. (!m. f(&m) = b m) /\
              (!m n. f(&(4 * m + 1) / &2 pow (n + 1)) =
                     l(f(&(2 * m + 1) / &2 pow n))) /\
              (!m n. f(&(4 * m + 3) / &2 pow (n + 1)) =
                     r(f(&(2 * m + 1) / &2 pow n)))`,
    REPEAT GEN_TAC THEN
    SUBGOAL_THEN
     `?f:num->num->A.
          (!m n. f (2 * m) (n + 1) = f m n) /\
          (!m. f m 0 = b m) /\
          (!m n. f (4 * m + 1) (n + 1) = l(f (2 * m + 1) n)) /\
          (!m n. f (4 * m + 3) (n + 1) = r(f (2 * m + 1) n))`
    MP_TAC THENL
     [MP_TAC(prove_recursive_functions_exist num_RECURSION
       `(!m. f m 0 = (b:num->A) m) /\
        (!m n. f m (SUC n) =
                  if EVEN m then f (m DIV 2) n
                  else if EVEN(m DIV 2)
                       then l(f ((m + 1) DIV 2) n)
                       else r(f (m DIV 2) n))`) THEN
      MATCH_MP_TAC MONO_EXISTS THEN
      X_GEN_TAC `f:num->num->A` THEN STRIP_TAC THEN
      RULE_ASSUM_TAC(REWRITE_RULE[ADD1]) THEN ASM_REWRITE_TAC[] THEN
      REWRITE_TAC[EVEN_MULT; ARITH_EVEN; ARITH_RULE `(2 * m) DIV 2 = m`] THEN
      REWRITE_TAC[ARITH_RULE `(4 * m + 1) DIV 2 = 2 * m`;
                  ARITH_RULE `(4 * m + 3) DIV 2 = 2 * m + 1`;
                  ARITH_RULE `((4 * m + 1) + 1) DIV 2 = 2 * m + 1`;
                  ARITH_RULE `((4 * m + 3) + 1) DIV 2 = 2 * m + 2`] THEN
      REWRITE_TAC[EVEN_ADD; EVEN_MULT; EVEN; ARITH_EVEN; SND];
      DISCH_THEN(X_CHOOSE_THEN `f:num->num->A`
       (CONJUNCTS_THEN2 MP_TAC ASSUME_TAC)) THEN
      DISCH_THEN(MP_TAC o MATCH_MP function_on_dyadic_rationals) THEN
      MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC THEN
      DISCH_THEN(fun th -> RULE_ASSUM_TAC(REWRITE_RULE[GSYM th])) THEN
      RULE_ASSUM_TAC(REWRITE_RULE[REAL_ARITH `x / &2 pow 0 = x`]) THEN
      ASM_REWRITE_TAC[]]) in
  let recursion_on_dyadic_rationals_1 = prove
   (`!b:A l r.
          ?f. (!m. f(&m / &2) = b) /\
              (!m n. 0 < n ==> f(&(4 * m + 1) / &2 pow (n + 1)) =
                               l(f(&(2 * m + 1) / &2 pow n))) /\
              (!m n. 0 < n ==> f(&(4 * m + 3) / &2 pow (n + 1)) =
                               r(f(&(2 * m + 1) / &2 pow n)))`,
    REPEAT GEN_TAC THEN
    MP_TAC(ISPECL [`(\n. b):num->A`; `l:A->A`; `r:A->A`]
          recursion_on_dyadic_rationals) THEN
    REWRITE_TAC[] THEN
    DISCH_THEN(X_CHOOSE_THEN `f:real->A` STRIP_ASSUME_TAC) THEN
    EXISTS_TAC `\x. (f:real->A)(&2 * x)` THEN
    ASM_REWRITE_TAC[REAL_ARITH `&2 * x / &2 = x`] THEN
    CONJ_TAC THEN GEN_TAC THEN INDUCT_TAC THEN REWRITE_TAC[LT_REFL] THEN
    ASM_SIMP_TAC[ADD_CLAUSES; real_pow; REAL_POW_EQ_0; REAL_OF_NUM_EQ;
      ARITH_EQ; REAL_FIELD `~(y = &0) ==> &2 * x / (&2 * y) = x / y`]) in
  let exists_function_unpair = prove
   (`(?f:A->B#C. P f) <=> (?f1 f2. P(\x. (f1 x,f2 x)))`,
    EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN STRIP_TAC THEN
    EXISTS_TAC `\x. FST((f:A->B#C) x)` THEN
    EXISTS_TAC `\x. SND((f:A->B#C) x)` THEN
    ASM_REWRITE_TAC[PAIR; ETA_AX]) in
  let dyadics_in_open_unit_interval = prove
   (`interval(vec 0,vec 1) INTER
      {lift(&m / &2 pow n) | m IN (:num) /\ n IN (:num)} =
      {lift(&m / &2 pow n) | 0 < m /\ m < 2 EXP n}`,
    MATCH_MP_TAC(SET_RULE
     `(!m n. (f m n) IN s <=> P m n)
      ==> s INTER {f m n | m IN UNIV /\ n IN UNIV} =
          {f m n | P m n}`) THEN
    REWRITE_TAC[IN_INTERVAL_1; LIFT_DROP; DROP_VEC] THEN
    SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_LDIV_EQ; REAL_LT_POW2] THEN
    SIMP_TAC[REAL_MUL_LZERO; REAL_MUL_LID; REAL_OF_NUM_POW; REAL_OF_NUM_LT]) in
  REPEAT STRIP_TAC THEN
  SUBGOAL_THEN
   `!a b m. m IN interval[a,b] /\ interval[a,b] SUBSET interval[vec 0,vec 1]
            ==> ?c d. drop a <= drop c /\ drop c <= drop m /\
                      drop m <= drop d /\ drop d <= drop b /\
                      (!x. x IN interval[c,d] ==> f x = f m) /\
                      (!x. x IN interval[a,c] DELETE c ==> ~(f x = f m)) /\
                      (!x. x IN interval[d,b] DELETE d ==> ~(f x = f m)) /\
                      (!x y. x IN interval[a,c] DELETE c /\
                             y IN interval[d,b] DELETE d
                             ==> ~((f:real^1->real^N) x = f y))`
  MP_TAC THENL
   [REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; SUBSET_INTERVAL_1] THEN
    REPEAT STRIP_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
    SUBGOAL_THEN
     `?c d. {x | x IN interval[a,b] /\ (f:real^1->real^N) x = f m} =
            interval[c,d]`
    MP_TAC THENL
     [SUBGOAL_THEN
       `{x | x IN interval[a,b] /\ (f:real^1->real^N) x = f m} =
        interval[a,b] INTER
        {x | x IN interval[vec 0,vec 1] /\ (f:real^1->real^N) x = f m}`
      SUBST1_TAC THENL
       [REWRITE_TAC[EXTENSION; IN_INTER; IN_INTERVAL_1; IN_ELIM_THM;
                    DROP_VEC] THEN
        GEN_TAC THEN EQ_TAC THEN SIMP_TAC[] THEN ASM_REAL_ARITH_TAC;
        ALL_TAC] THEN
      SUBGOAL_THEN
       `?c d. {x | x IN interval[vec 0,vec 1] /\ (f:real^1->real^N) x = f m} =
              interval[c,d]`
      MP_TAC THENL
       [ASM_REWRITE_TAC[GSYM CONNECTED_COMPACT_INTERVAL_1] THEN
        ONCE_REWRITE_TAC[SET_RULE
         `{x | x IN s /\ P x} = s INTER {x | x IN s /\ P x}`] THEN
        MATCH_MP_TAC COMPACT_INTER_CLOSED THEN
        REWRITE_TAC[COMPACT_INTERVAL] THEN
        MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_CONSTANT THEN
        ASM_REWRITE_TAC[CLOSED_INTERVAL];
        STRIP_TAC THEN ASM_REWRITE_TAC[INTER_INTERVAL_1] THEN MESON_TAC[]];
      ALL_TAC] THEN
    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `c:real^1` THEN
    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real^1` THEN DISCH_TAC THEN
    SUBGOAL_THEN `m IN interval[c:real^1,d]` MP_TAC THENL
     [FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
      REWRITE_TAC[IN_ELIM_THM; IN_INTERVAL_1; DROP_VEC] THEN
                  ASM_REAL_ARITH_TAC;
      REWRITE_TAC[IN_INTERVAL_1; IN_DELETE] THEN STRIP_TAC] THEN
    SUBGOAL_THEN `{c:real^1,d} SUBSET interval[c,d]` MP_TAC THENL
     [ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET; IN_INTERVAL_1] THEN
      ASM_REAL_ARITH_TAC;
      FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV)
       [GSYM th]) THEN
      REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET; IN_ELIM_THM; IN_INTERVAL_1] THEN
      STRIP_TAC THEN ASM_REWRITE_TAC[]] THEN
    CONJ_TAC THENL
     [GEN_TAC THEN REWRITE_TAC[GSYM IN_INTERVAL_1] THEN
      FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC  (LAND_CONV o RAND_CONV)
       [GSYM th]) THEN SIMP_TAC[IN_ELIM_THM];
      ALL_TAC] THEN
    GEN_REWRITE_TAC I [CONJ_ASSOC] THEN CONJ_TAC THENL
     [CONJ_TAC THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
      `{x | x IN s /\ f x = a} = t
       ==> (!x. P x ==> x IN s) /\ (!x. P x /\ Q x ==> ~(x IN t))
           ==> !x. P x /\ Q x ==> ~(f x = a)`)) THEN
      REWRITE_TAC[IN_INTERVAL_1; GSYM DROP_EQ] THEN ASM_REAL_ARITH_TAC;
      ALL_TAC] THEN
    MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN
    REWRITE_TAC[GSYM DROP_EQ] THEN STRIP_TAC THEN
    SUBGOAL_THEN `{x:real^1,y} INTER interval[c,d] = {}` MP_TAC THENL
     [REWRITE_TAC[SET_RULE `{a,b} INTER s = {} <=> ~(a IN s) /\ ~(b IN s)`;
                  IN_INTERVAL_1] THEN
      ASM_REAL_ARITH_TAC;
      FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC
       (LAND_CONV o LAND_CONV o RAND_CONV) [GSYM th])] THEN
    REWRITE_TAC[SET_RULE `{a,b} INTER s = {} <=> ~(a IN s) /\ ~(b IN s)`] THEN
    REWRITE_TAC[IN_ELIM_THM; IN_INTERVAL_1] THEN
    ASM_CASES_TAC `(f:real^1->real^N) x = f m` THENL
     [ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN
    ASM_CASES_TAC `(f:real^1->real^N) y = f m` THENL
     [ASM_REWRITE_TAC[] THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN
    ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM IS_INTERVAL_CONNECTED_1] o
                  SPEC `(f:real^1->real^N) y`) THEN
    ASM_REWRITE_TAC[IS_INTERVAL_1] THEN DISCH_THEN(MP_TAC o SPECL
     [`x:real^1`; `y:real^1`; `m:real^1`]) THEN
    ASM_REWRITE_TAC[IN_ELIM_THM; IN_INTERVAL_1; DROP_VEC] THEN
    ASM_REAL_ARITH_TAC;
    REWRITE_TAC[RIGHT_IMP_EXISTS_THM; SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN
    MAP_EVERY X_GEN_TAC
     [`leftcut:real^1->real^1->real^1->real^1`;
      `rightcut:real^1->real^1->real^1->real^1`] THEN
    STRIP_TAC] THEN
  FIRST_ASSUM(MP_TAC o SPECL
   [`vec 0:real^1`; `vec 1:real^1`; `vec 0:real^1`]) THEN
  REWRITE_TAC[SUBSET_REFL; ENDS_IN_UNIT_INTERVAL] THEN ABBREV_TAC
   `u = (rightcut:real^1->real^1->real^1->real^1) (vec 0) (vec 1) (vec 0)` THEN
  REWRITE_TAC[CONJ_ASSOC; REAL_LE_ANTISYM; DROP_EQ] THEN
  REWRITE_TAC[GSYM CONJ_ASSOC] THEN ONCE_REWRITE_TAC[IMP_CONJ] THEN
  DISCH_THEN(SUBST1_TAC o SYM) THEN
  REWRITE_TAC[INTERVAL_SING; SET_RULE `~(x IN ({a} DELETE a))`] THEN
  STRIP_TAC THEN
  FIRST_ASSUM(MP_TAC o SPECL
   [`u:real^1`; `vec 1:real^1`; `vec 1:real^1`]) THEN
  REWRITE_TAC[ENDS_IN_INTERVAL; SUBSET_INTERVAL_1; INTERVAL_NE_EMPTY_1] THEN
  ASM_REWRITE_TAC[REAL_LE_REFL] THEN ABBREV_TAC
   `v = (leftcut:real^1->real^1->real^1->real^1) u (vec 1) (vec 1)` THEN
  ONCE_REWRITE_TAC[TAUT
    `a /\ b /\ c /\ d /\ e <=> (c /\ d) /\ a /\ b /\ e`] THEN
  REWRITE_TAC[REAL_LE_ANTISYM; DROP_EQ] THEN
  ONCE_REWRITE_TAC[IMP_CONJ] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
  REWRITE_TAC[INTERVAL_SING; SET_RULE `~(x IN ({a} DELETE a))`] THEN
  STRIP_TAC THEN
  SUBGOAL_THEN
   `!x. x IN interval[vec 0,v] DELETE v
        ==> ~((f:real^1->real^N) x = f(vec 1))`
  ASSUME_TAC THENL
   [X_GEN_TAC `t:real^1` THEN
    REWRITE_TAC[IN_DELETE; IN_INTERVAL_1; GSYM DROP_EQ] THEN STRIP_TAC THEN
    ASM_CASES_TAC `drop t < drop u` THENL
     [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
       `~(f1 = f0) ==> ft = f0 ==> ~(ft = f1)`));
      ALL_TAC] THEN
    FIRST_X_ASSUM MATCH_MP_TAC THEN
    ASM_REWRITE_TAC[IN_INTERVAL_1; IN_DELETE; GSYM DROP_EQ] THEN
    ASM_REAL_ARITH_TAC;
    UNDISCH_THEN
      `!x. x IN interval[u,v] DELETE v ==> ~((f:real^1->real^N) x = f (vec 1))`
      (K ALL_TAC)] THEN
  MP_TAC(ISPECL
   [`(u:real^1,v:real^1)`;
    `\(a,b). (a:real^1,leftcut a b (midpoint(a,b)):real^1)`;
    `\(a,b). (rightcut a b (midpoint(a,b)):real^1,b:real^1)`]
        recursion_on_dyadic_rationals_1) THEN
  REWRITE_TAC[exists_function_unpair; PAIR_EQ] THEN
  REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
  MAP_EVERY X_GEN_TAC [`a:real->real^1`; `b:real->real^1`] THEN
  ABBREV_TAC `(c:real->real^1) x = midpoint(a x,b x)` THEN
  REWRITE_TAC[TAUT `a ==> b /\ c <=> (a ==> b) /\ (a ==> c)`] THEN
  REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC THEN
  SUBGOAL_THEN
   `!m n. drop u <= drop(a(&m / &2 pow n)) /\
          drop(a(&m / &2 pow n)) <= drop(b(&m / &2 pow n)) /\
          drop(b(&m / &2 pow n)) <= drop v`
  MP_TAC THENL
   [GEN_REWRITE_TAC I [SWAP_FORALL_THM] THEN MATCH_MP_TAC num_INDUCTION THEN
    CONJ_TAC THENL
     [REWRITE_TAC[REAL_ARITH `x / &2 pow 0 = (&2 * x) / &2`] THEN
      ASM_REWRITE_TAC[REAL_OF_NUM_MUL; REAL_LE_REFL];
      X_GEN_TAC `n:num` THEN DISCH_THEN(LABEL_TAC "*")] THEN
    X_GEN_TAC `p:num` THEN DISJ_CASES_TAC(SPEC `p:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN
      REWRITE_TAC[GSYM REAL_OF_NUM_MUL; real_pow] THEN
      ASM_SIMP_TAC[REAL_LT_POW2; REAL_FIELD
       `&0 < y ==> (&2 * x) / (&2 * y) = x / y`];
      ALL_TAC] THEN
    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
    DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN
    DISJ_CASES_TAC(ARITH_RULE `n = 0 \/ 0 < n`) THENL
     [ASM_REWRITE_TAC[real_pow; REAL_MUL_RID; REAL_LE_REFL];
      REWRITE_TAC[ADD1]] THEN
    DISJ_CASES_TAC(SPEC `m:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `r:num` SUBST_ALL_TAC) THEN
      ASM_SIMP_TAC[ARITH_RULE `2 * 2 * r = 4 * r`];
      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `r:num` SUBST_ALL_TAC) THEN
      ASM_SIMP_TAC[ARITH_RULE `2 * SUC(2 * r) + 1 = 4 * r + 3`]] THEN
    (FIRST_X_ASSUM(MP_TAC o SPECL
      [`a(&(2 * r + 1) / &2 pow n):real^1`;
       `b(&(2 * r + 1) / &2 pow n):real^1`;
       `c(&(2 * r + 1) / &2 pow n):real^1`]) THEN
     ANTS_TAC THENL
      [FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
        [GSYM th]) THEN
       REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
       REWRITE_TAC[DROP_CMUL; DROP_ADD] THEN
       UNDISCH_TAC `drop(vec 0) <= drop u` THEN
       UNDISCH_TAC `drop v <= drop (vec 1)`;
       ALL_TAC] THEN
     REMOVE_THEN "*" (MP_TAC o SPEC `2 * r + 1`) THEN REAL_ARITH_TAC);
    REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC] THEN
  SUBGOAL_THEN `!m n. drop(vec 0) <= drop(a(&m / &2 pow n))` ASSUME_TAC THENL
   [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC] THEN
  SUBGOAL_THEN `!m n. drop(b(&m / &2 pow n)) <= drop(vec 1)` ASSUME_TAC THENL
   [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC] THEN
  SUBGOAL_THEN
   `!m n. drop(a(&m / &2 pow n)) <= drop(c(&m / &2 pow n)) /\
          drop(c(&m / &2 pow n)) <= drop(b(&m / &2 pow n))`
  MP_TAC THENL
   [UNDISCH_THEN `!x:real. midpoint(a x:real^1,b x) = c x`
      (fun th -> REWRITE_TAC[GSYM th]) THEN
    REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
    ASM_REWRITE_TAC[DROP_CMUL; DROP_ADD; REAL_ARITH
     `a <= inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a <= b`];
    REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC] THEN
  SUBGOAL_THEN
   `!i m n j. ODD j /\
              abs(&i / &2 pow m - &j / &2 pow n) < inv(&2 pow n)
              ==> drop(a(&j / &2 pow n)) <= drop(c(&i / &2 pow m)) /\
                  drop(c(&i / &2 pow m)) <= drop(b(&j / &2 pow n))`
  ASSUME_TAC THENL
   [REPLICATE_TAC 3 GEN_TAC THEN WF_INDUCT_TAC `m - n:num` THEN
    DISJ_CASES_TAC(ARITH_RULE `m <= n \/ n:num < m`) THENL
     [GEN_TAC THEN STRIP_TAC THEN
      MP_TAC(SPEC `abs(&2 pow n) * abs(&i / &2 pow m - &j / &2 pow n)`
                REAL_ABS_INTEGER_LEMMA) THEN
      MATCH_MP_TAC(TAUT
       `i /\ ~b /\ (n ==> p) ==> (i /\ ~n ==> b) ==> p`) THEN
      REPEAT CONJ_TAC THENL
       [REWRITE_TAC[GSYM REAL_ABS_MUL; INTEGER_ABS] THEN
        REWRITE_TAC[REAL_ARITH
         `n * (x / m - y / n):real = x * (n / m) - y * (n / n)`] THEN
        ASM_SIMP_TAC[GSYM REAL_POW_SUB; LE_REFL; REAL_OF_NUM_EQ; ARITH_EQ] THEN
        MESON_TAC[INTEGER_CLOSED];
        SIMP_TAC[REAL_ABS_MUL; REAL_ABS_ABS; REAL_ABS_POW; REAL_ABS_NUM] THEN
        REWRITE_TAC[REAL_ARITH `~(&1 <= x * y) <=> y * x < &1`] THEN
        SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_POW2] THEN
        ASM_REWRITE_TAC[REAL_ARITH `&1 / x = inv x`];
        ASM_SIMP_TAC[REAL_ABS_POW; REAL_ABS_NUM; REAL_ENTIRE; REAL_LT_IMP_NZ;
          REAL_LT_POW2; REAL_ARITH `abs(x - y) = &0 <=> x = y`]];
      ALL_TAC] THEN
    X_GEN_TAC `k:num` THEN REWRITE_TAC[IMP_CONJ; ODD_EXISTS] THEN
    DISCH_THEN(X_CHOOSE_THEN `j:num` SUBST1_TAC) THEN
    DISJ_CASES_TAC(ARITH_RULE `n = 0 \/ 0 < n`) THENL
     [ASM_REWRITE_TAC[REAL_ARITH `x / &2 pow 0 = (&2 * x) / &2`] THEN
      ASM_REWRITE_TAC[REAL_OF_NUM_MUL] THEN ASM_MESON_TAC[REAL_LE_TRANS];
      ALL_TAC] THEN
    UNDISCH_THEN `n:num < m`
      (fun th -> let th' = MATCH_MP
                   (ARITH_RULE `n < m ==> m - SUC n < m - n`) th in
                 FIRST_X_ASSUM(MP_TAC o C MATCH_MP th')) THEN
    REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH
     `&i / &2 pow m = &(2 * j + 1) / &2 pow n \/
      &i / &2 pow m < &(2 * j + 1) / &2 pow n \/
      &(2 * j + 1) / &2 pow n < &i / &2 pow m`)
    THENL
     [ASM_REWRITE_TAC[ADD1];
      DISCH_THEN(MP_TAC o SPEC `4 * j + 1`) THEN
      REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH] THEN ASM_SIMP_TAC[ADD1] THEN
      MATCH_MP_TAC MONO_IMP THEN CONJ_TAC THENL
       [MATCH_MP_TAC(REAL_ARITH
         `x < i /\ &2 * n1 = n /\ j + n1 = i
          ==> abs(x - i) < n ==> abs(x - j) < n1`) THEN
        ASM_REWRITE_TAC[REAL_ARITH `a / b + inv b = (a + &1) / b`] THEN
        REWRITE_TAC[real_div; REAL_POW_ADD; REAL_INV_MUL] THEN
        REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
        REAL_ARITH_TAC;
        MATCH_MP_TAC(REAL_ARITH
         `b' <= b ==> a <= c /\ c <= b' ==> a <= c /\ c <= b`) THEN
        FIRST_X_ASSUM(MP_TAC o SPECL
         [`a(&(2 * j + 1) / &2 pow n):real^1`;
          `b(&(2 * j + 1) / &2 pow n):real^1`;
          `c(&(2 * j + 1) / &2 pow n):real^1`]) THEN
        ANTS_TAC THENL [ALL_TAC; REAL_ARITH_TAC] THEN
        FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
          [GSYM th]) THEN
        REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
        REWRITE_TAC[DROP_CMUL; DROP_ADD] THEN
        ASM_REWRITE_TAC[DROP_CMUL; DROP_ADD; REAL_ARITH
         `a <= inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a <= b`]];
      DISCH_THEN(MP_TAC o SPEC `4 * j + 3`) THEN
      REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH] THEN ASM_SIMP_TAC[ADD1] THEN
      MATCH_MP_TAC MONO_IMP THEN CONJ_TAC THENL
       [MATCH_MP_TAC(REAL_ARITH
         `i < x /\ &2 * n1 = n /\ j - n1 = i
          ==> abs(x - i) < n ==> abs(x - j) < n1`) THEN
        ASM_REWRITE_TAC[REAL_ARITH `a / b - inv b = (a - &1) / b`] THEN
        REWRITE_TAC[real_div; REAL_POW_ADD; REAL_INV_MUL] THEN
        REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
        REAL_ARITH_TAC;
        MATCH_MP_TAC(REAL_ARITH
         `a <= a' ==> a' <= c /\ c <= b ==> a <= c /\ c <= b`) THEN
        FIRST_X_ASSUM(MP_TAC o SPECL
         [`a(&(2 * j + 1) / &2 pow n):real^1`;
          `b(&(2 * j + 1) / &2 pow n):real^1`;
          `c(&(2 * j + 1) / &2 pow n):real^1`]) THEN
        ANTS_TAC THENL [ALL_TAC; REAL_ARITH_TAC] THEN
        FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
          [GSYM th]) THEN
        REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
        REWRITE_TAC[DROP_CMUL; DROP_ADD] THEN
        ASM_REWRITE_TAC[DROP_CMUL; DROP_ADD; REAL_ARITH
         `a <= inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a <= b`]]];
    ALL_TAC] THEN
  SUBGOAL_THEN
   `!m n. ODD m ==> abs(drop(a(&m / &2 pow n)) - drop(b(&m / &2 pow n)))
                    <= &2 / &2 pow n`
  ASSUME_TAC THENL
   [ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN INDUCT_TAC THENL
     [ASM_REWRITE_TAC[REAL_ARITH `x / &2 pow 0 = (&2 * x) / &2`] THEN
      ASM_REWRITE_TAC[REAL_OF_NUM_MUL] THEN CONV_TAC NUM_REDUCE_CONV THEN
      RULE_ASSUM_TAC(REWRITE_RULE[DROP_VEC]) THEN ASM_REAL_ARITH_TAC;
      ALL_TAC] THEN
    X_GEN_TAC `m:num` THEN REWRITE_TAC[ODD_EXISTS] THEN
    DISCH_THEN(X_CHOOSE_THEN `k:num` SUBST1_TAC) THEN
    DISJ_CASES_TAC(ARITH_RULE `n = 0 \/ 0 < n`) THENL
     [ASM_REWRITE_TAC[ARITH; REAL_POW_1] THEN
      RULE_ASSUM_TAC(REWRITE_RULE[DROP_VEC]) THEN ASM_REAL_ARITH_TAC;
      ALL_TAC] THEN
    DISJ_CASES_TAC(SPEC `k:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `j:num` SUBST1_TAC) THEN
      REWRITE_TAC[ARITH_RULE `SUC(2 * 2 * j) = 4 * j + 1`] THEN
      ASM_SIMP_TAC[ADD1] THEN
      MATCH_MP_TAC(REAL_ARITH
       `drop c = (drop a + drop b) / &2 /\
        abs(drop a - drop b) <= &2 * k /\
        drop a <= drop(leftcut a b c) /\
        drop(leftcut a b c) <= drop c
        ==> abs(drop a - drop(leftcut a b c)) <= k`);
      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `j:num` SUBST1_TAC) THEN
      REWRITE_TAC[ARITH_RULE `SUC(2 * SUC(2 * j)) = 4 * j + 3`] THEN
      ASM_SIMP_TAC[ADD1] THEN
      MATCH_MP_TAC(REAL_ARITH
       `drop c = (drop a + drop b) / &2 /\
        abs(drop a - drop b) <= &2 * k /\
        drop c <= drop(rightcut a b c) /\
        drop(rightcut a b c) <= drop b
        ==> abs(drop(rightcut a b c) - drop b) <= k`)] THEN
    (CONJ_TAC THENL
      [UNDISCH_THEN `!x:real. midpoint(a x:real^1,b x) = c x`
        (fun th -> REWRITE_TAC[GSYM th]) THEN
       REWRITE_TAC[midpoint; DROP_CMUL; DROP_ADD] THEN REAL_ARITH_TAC;
       ALL_TAC] THEN
     CONJ_TAC THENL
      [REWRITE_TAC[real_div; REAL_POW_ADD; REAL_INV_MUL] THEN
       REWRITE_TAC[REAL_ARITH `&2 * x * inv y * inv(&2 pow 1) = x / y`] THEN
       ASM_SIMP_TAC[GSYM real_div; ODD_ADD; ODD_MULT; ARITH];
       ALL_TAC] THEN
     FIRST_X_ASSUM(MP_TAC o SPECL
      [`a(&(2 * j + 1) / &2 pow n):real^1`;
       `b(&(2 * j + 1) / &2 pow n):real^1`;
       `c(&(2 * j + 1) / &2 pow n):real^1`]) THEN
     ANTS_TAC THENL [ALL_TAC; REAL_ARITH_TAC] THEN
     FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
       [GSYM th]) THEN
     REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
     REWRITE_TAC[DROP_CMUL; DROP_ADD] THEN
     ASM_REWRITE_TAC[DROP_CMUL; DROP_ADD; REAL_ARITH
      `a <= inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a <= b`]);
    ALL_TAC] THEN
  SUBGOAL_THEN
   `!n j. 0 < 2 * j /\ 2 * j < 2 EXP n
          ==> (f:real^1->real^N)(b(&(2 * j - 1) / &2 pow n)) =
              f(a(&(2 * j + 1) / &2 pow n))`
  ASSUME_TAC THENL
   [MATCH_MP_TAC num_INDUCTION THEN CONJ_TAC THENL
     [REWRITE_TAC[ARITH_RULE `0 < 2 * j <=> 0 < j`;
                  ARITH_RULE `2 * j < 2 <=> j < 1`] THEN
      ARITH_TAC;
      ALL_TAC] THEN
    X_GEN_TAC `n:num` THEN DISCH_THEN(LABEL_TAC "+") THEN
    DISJ_CASES_TAC(ARITH_RULE `n = 0 \/ 0 < n`) THENL
     [ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV THEN
      REWRITE_TAC[ARITH_RULE `0 < 2 * j <=> 0 < j`;
                   ARITH_RULE `2 * j < 2  <=> j < 1`] THEN
      ARITH_TAC;
      ALL_TAC] THEN
    X_GEN_TAC `k:num` THEN DISJ_CASES_TAC(SPEC `k:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `j:num` SUBST1_TAC) THEN
      REWRITE_TAC[EXP; ARITH_RULE `0 < 2 * j <=> 0 < j`; LT_MULT_LCANCEL] THEN
      CONV_TAC NUM_REDUCE_CONV THEN
      ASM_SIMP_TAC[ARITH_RULE `0 < j ==> 2 * 2 * j - 1 = 4 * (j - 1) + 3`;
        ADD1; ARITH_RULE `2 * 2 * j + 1 = 4 * j + 1`] THEN
      SIMP_TAC[ARITH_RULE `0 < j ==> 2 * (j - 1) + 1 = 2 * j - 1`] THEN
      STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_ARITH_TAC;
      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `j:num` SUBST1_TAC) THEN
      STRIP_TAC THEN
      ASM_SIMP_TAC[ADD1; ARITH_RULE `2 * SUC(2 * j) - 1 = 4 * j + 1`;
                   ARITH_RULE `2 * SUC(2 * j) + 1 = 4 * j + 3`] THEN
      FIRST_X_ASSUM(MP_TAC o SPECL
       [`a(&(2 * j + 1) / &2 pow n):real^1`;
        `b(&(2 * j + 1) / &2 pow n):real^1`;
        `c(&(2 * j + 1) / &2 pow n):real^1`]) THEN
      ANTS_TAC THENL
       [FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
         [GSYM th]) THEN
        REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
        REWRITE_TAC[DROP_CMUL; DROP_ADD] THEN
        ASM_REWRITE_TAC[DROP_CMUL; DROP_ADD; REAL_ARITH
         `a <= inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a <= b`];
        REPLICATE_TAC 4 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
        DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
        MATCH_MP_TAC(MESON[]
         `a IN s /\ b IN s ==> (!x. x IN s ==> f x = c) ==> f a = f b`) THEN
        REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY_1] THEN
        ASM_MESON_TAC[REAL_LE_TRANS]]];
    ALL_TAC] THEN
  SUBGOAL_THEN
   `!n j. 0 < j /\ j < 2 EXP n
          ==> (f:real^1->real^N)(b(&(2 * j - 1) / &2 pow (n + 1))) =
              f(c(&j / &2 pow n)) /\
              f(a(&(2 * j + 1) / &2 pow (n + 1))) = f(c(&j / &2 pow n))`
  ASSUME_TAC THENL
   [MATCH_MP_TAC num_INDUCTION THEN
    REWRITE_TAC[ARITH_RULE `~(0 < j /\ j < 2 EXP 0)`] THEN
    X_GEN_TAC `n:num` THEN DISCH_THEN(LABEL_TAC "*") THEN
    X_GEN_TAC `j:num` THEN
    DISJ_CASES_TAC(SPEC `j:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `k:num` SUBST1_TAC) THEN
      REWRITE_TAC[ADD_CLAUSES; EXP; ARITH_RULE `0 < 2 * k <=> 0 < k`;
                  ARITH_RULE `2 * x < 2 * y <=> x < y`] THEN STRIP_TAC THEN
      REMOVE_THEN "*" (MP_TAC o SPEC `k:num`) THEN
      ASM_REWRITE_TAC[] THEN
      MATCH_MP_TAC(MESON[]
       `c' = c /\ a' = a /\ b' = b
        ==> b = c /\ a = c ==> b' = c' /\ a' = c'`) THEN
      REPEAT CONJ_TAC THEN AP_TERM_TAC THENL
       [AP_TERM_TAC THEN
        REWRITE_TAC[real_pow; real_div; REAL_INV_MUL;
                    GSYM REAL_OF_NUM_MUL] THEN
        REAL_ARITH_TAC;
        REWRITE_TAC[ADD1; ARITH_RULE `2 * 2 * n = 4 * n`] THEN
        FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC;
        SUBGOAL_THEN `k = PRE k + 1` SUBST1_TAC THENL
         [ASM_ARITH_TAC; ALL_TAC] THEN
        REWRITE_TAC[ARITH_RULE `2 * (k + 1) - 1 = 2 * k + 1`;
                    ARITH_RULE `2 * 2 * (k + 1) - 1 = 4 * k + 3`] THEN
        REWRITE_TAC[ADD1] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ARITH_TAC];
      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `k:num` SUBST1_TAC) THEN
      REWRITE_TAC[EXP; ARITH_RULE `SUC(2 * k) < 2 * n <=> k < n`] THEN
      STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
       [`a(&(2 * k + 1) / &2 pow (SUC n)):real^1`;
        `b(&(2 * k + 1) / &2 pow (SUC n)):real^1`;
        `c(&(2 * k + 1) / &2 pow (SUC n)):real^1`]) THEN
      ANTS_TAC THENL
       [ASM_REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1];
        REPLICATE_TAC 4 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
        DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC)] THEN
      REWRITE_TAC[ARITH_RULE `SUC(2 * k) = 2 * k + 1`] THEN
      DISCH_THEN(fun th -> CONJ_TAC THEN MATCH_MP_TAC th) THEN
      ASM_SIMP_TAC[ARITH_RULE `2 * (2 * k + 1) - 1 = 4 * k + 1`; ADD1;
                   ARITH_RULE `2 * (2 * k + 1) + 1 = 4 * k + 3`;
                   ARITH_RULE `0 < n + 1`] THEN
      ASM_REWRITE_TAC[IN_INTERVAL_1; GSYM ADD1] THEN
      ASM_SIMP_TAC[ARITH_RULE `SUC(2 * k) = 2 * k + 1`] THEN
      ASM_REAL_ARITH_TAC];
    ALL_TAC] THEN
  ONCE_REWRITE_TAC[HOMEOMORPHIC_SYM] THEN
  MATCH_MP_TAC HOMEOMORPHIC_COMPACT THEN
  REWRITE_TAC[COMPACT_INTERVAL] THEN
  MP_TAC(ISPECL [`\x. (f:real^1->real^N)(c(drop x))`;
                 `interval(vec 0,vec 1) INTER
                  {lift(&m / &2 pow n) | m IN (:num) /\ n IN (:num)}`]
        UNIFORMLY_CONTINUOUS_EXTENDS_TO_CLOSURE) THEN
  SIMP_TAC[closure_dyadic_rationals_in_convex_set_pos_1;
           CONVEX_INTERVAL; INTERIOR_OPEN; OPEN_INTERVAL;
           UNIT_INTERVAL_NONEMPTY; IN_INTERVAL_1; REAL_LT_IMP_LE; DROP_VEC;
           CLOSURE_OPEN_INTERVAL] THEN
  REWRITE_TAC[dyadics_in_open_unit_interval] THEN
  ANTS_TAC THENL
   [REWRITE_TAC[uniformly_continuous_on; FORALL_IN_GSPEC] THEN
    X_GEN_TAC `e:real` THEN DISCH_TAC THEN SUBGOAL_THEN
     `(f:real^1->real^N) uniformly_continuous_on interval[vec 0,vec 1]`
    MP_TAC THENL
     [ASM_SIMP_TAC[COMPACT_UNIFORMLY_CONTINUOUS; COMPACT_INTERVAL];
      REWRITE_TAC[uniformly_continuous_on]] THEN
    DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN
    DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
    MP_TAC(SPECL [`inv(&2)`; `min (d:real) (&1 / &4)`] REAL_ARCH_POW_INV) THEN
    ASM_REWRITE_TAC[REAL_HALF; REAL_POW_INV; REAL_LT_MIN] THEN
    CONV_TAC REAL_RAT_REDUCE_CONV THEN
    DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN
    ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THEN
    CONV_TAC REAL_RAT_REDUCE_CONV THEN STRIP_TAC THEN
    EXISTS_TAC `inv(&2 pow n)` THEN
    REWRITE_TAC[REAL_LT_POW2; REAL_LT_INV_EQ] THEN
    REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
    REWRITE_TAC[FORALL_IN_GSPEC] THEN
    SUBGOAL_THEN
     `!i j m. 0 < i /\ i < 2 EXP m /\ 0 < j /\ j < 2 EXP n /\
              abs(&i / &2 pow m - &j / &2 pow n) < inv(&2 pow n)
              ==> norm((f:real^1->real^N)(c(&i / &2 pow m)) -
                       f(c(&j / &2 pow n))) < e / &2`
    ASSUME_TAC THENL
     [REPEAT GEN_TAC THEN
      REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
      DISCH_THEN(DISJ_CASES_THEN MP_TAC o MATCH_MP (REAL_ARITH
       `abs(x - a) < e
        ==> x = a \/
            abs(x - (a - e / &2)) < e / &2 \/
            abs(x - (a + e / &2)) < e / &2`))
      THENL
       [DISCH_THEN SUBST1_TAC THEN
        ASM_REWRITE_TAC[VECTOR_SUB_REFL; NORM_0; REAL_HALF];
        ALL_TAC] THEN
      SUBGOAL_THEN
       `&j / &2 pow n = &(2 * j) / &2 pow (n + 1)`
       (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th])
      THENL
       [REWRITE_TAC[REAL_POW_ADD; real_div; REAL_INV_MUL;
                    GSYM REAL_OF_NUM_MUL] THEN
        REAL_ARITH_TAC;
        ALL_TAC] THEN
      REWRITE_TAC[real_div; GSYM REAL_INV_MUL] THEN
      REWRITE_TAC[GSYM real_div;
           GSYM(ONCE_REWRITE_RULE[REAL_MUL_SYM] (CONJUNCT2 real_pow))] THEN
      REWRITE_TAC[ADD1; REAL_ARITH `x / n + inv n = (x + &1) / n`;
                  REAL_ARITH `x / n - inv n = (x - &1) / n`] THEN
      ASM_SIMP_TAC[REAL_OF_NUM_SUB; ARITH_RULE `0 < j ==> 1 <= 2 * j`] THEN
      REWRITE_TAC[REAL_OF_NUM_ADD] THEN STRIP_TAC THENL
       [SUBGOAL_THEN `(f:real^1->real^N)(c(&j / &2 pow n)) =
                      f(b (&(2 * j - 1) / &2 pow (n + 1)))`
        SUBST1_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC];
        SUBGOAL_THEN `(f:real^1->real^N)(c(&j / &2 pow n)) =
                      f(a (&(2 * j + 1) / &2 pow (n + 1)))`
        SUBST1_TAC THENL [ASM_SIMP_TAC[]; ALL_TAC]] THEN
      REWRITE_TAC[GSYM dist] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
      REWRITE_TAC[IN_INTERVAL_1] THEN
      REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC]) THEN
      FIRST_X_ASSUM(MP_TAC o SPECL [`i:num`; `m:num`; `n + 1`]) THENL
       [DISCH_THEN(MP_TAC o SPEC `2 * j - 1`) THEN REWRITE_TAC[ODD_SUB];
        DISCH_THEN(MP_TAC o SPEC `2 * j + 1`) THEN REWRITE_TAC[ODD_ADD]] THEN
      ASM_REWRITE_TAC[ODD_MULT; ARITH; ARITH_RULE `1 < 2 * j <=> 0 < j`] THEN
      REWRITE_TAC[DIST_REAL; GSYM drop] THENL
       [MATCH_MP_TAC(NORM_ARITH
         `!t. abs(a - b) <= t /\ t < d
              ==> a <= c /\ c <= b ==> abs(c - b) < d`);
        MATCH_MP_TAC(NORM_ARITH
         `!t. abs(a - b) <= t /\ t < d
              ==> a <= c /\ c <= b ==> abs(c - a) < d`)] THEN
      EXISTS_TAC `&2 / &2 pow (n + 1)` THEN
      (CONJ_TAC THENL
        [FIRST_X_ASSUM MATCH_MP_TAC THEN
         REWRITE_TAC[ODD_SUB; ODD_ADD; ODD_MULT; ARITH_ODD] THEN
         ASM_REWRITE_TAC[ARITH_RULE `1 < 2 * j <=> 0 < j`];
         REWRITE_TAC[REAL_POW_ADD; real_div; REAL_INV_MUL] THEN
         ASM_REAL_ARITH_TAC]);
      ALL_TAC] THEN
    MAP_EVERY X_GEN_TAC [`i:num`; `m:num`] THEN STRIP_TAC THEN
    MAP_EVERY X_GEN_TAC [`k:num`; `p:num`] THEN STRIP_TAC THEN
    REWRITE_TAC[DIST_LIFT; LIFT_DROP] THEN STRIP_TAC THEN
    SUBGOAL_THEN
     `?j. 0 < j /\ j < 2 EXP n /\
          abs(&i / &2 pow m - &j / &2 pow n) < inv(&2 pow n) /\
          abs(&k / &2 pow p - &j / &2 pow n) < inv(&2 pow n)`
    STRIP_ASSUME_TAC THENL
     [MP_TAC(SPEC `max (&2 pow n * &i / &2 pow m)
                       (&2 pow n * &k / &2 pow p)`
        FLOOR_POS) THEN
      SIMP_TAC[REAL_LE_MUL; REAL_LE_MAX; REAL_LE_DIV;
               REAL_POS; REAL_POW_LE] THEN
      DISCH_THEN(X_CHOOSE_TAC `j:num`) THEN
      MP_TAC(SPEC `max (&2 pow n * &i / &2 pow m)
                       (&2 pow n * &k / &2 pow p)` FLOOR) THEN
      ASM_REWRITE_TAC[REAL_LE_MAX; REAL_MAX_LT] THEN
      ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
      SIMP_TAC[GSYM REAL_LE_LDIV_EQ; GSYM REAL_LT_RDIV_EQ; REAL_LT_POW2] THEN
      REWRITE_TAC[REAL_ARITH `(j + &1) / n = j / n + inv n`] THEN
      ASM_CASES_TAC `j = 0` THENL
       [ASM_REWRITE_TAC[REAL_ARITH `&0 / x = &0`; REAL_ADD_LID] THEN
        DISCH_TAC THEN EXISTS_TAC `1` THEN CONV_TAC NUM_REDUCE_CONV THEN
        REWRITE_TAC[ARITH_RULE `1 < n <=> 2 EXP 1 <= n`] THEN
        ASM_SIMP_TAC[LE_EXP; LE_1] THEN CONV_TAC NUM_REDUCE_CONV THEN
        MATCH_MP_TAC(REAL_ARITH
         `&0 < x /\ x < inv n /\ &0 < y /\ y < inv n
          ==> abs(x - &1 / n) < inv n /\ abs(y - &1 / n) < inv n`) THEN
        ASM_SIMP_TAC[REAL_LT_DIV; REAL_OF_NUM_LT; REAL_LT_POW2];
        DISCH_TAC THEN EXISTS_TAC `j:num` THEN ASM_SIMP_TAC[LE_1] THEN
        REWRITE_TAC[GSYM REAL_OF_NUM_LT; GSYM REAL_OF_NUM_POW] THEN
        CONJ_TAC THENL [ALL_TAC; ASM_REAL_ARITH_TAC] THEN
        FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [GSYM th]) THEN
        SIMP_TAC[GSYM REAL_NOT_LE; REAL_LE_FLOOR; INTEGER_CLOSED] THEN
        REWRITE_TAC[REAL_NOT_LE; REAL_MAX_LT] THEN
        REWRITE_TAC[REAL_ARITH `n * x < n <=> n * x < n * &1`] THEN
        SIMP_TAC[REAL_LT_LMUL_EQ; REAL_LT_POW2; REAL_LT_LDIV_EQ] THEN
        ASM_REWRITE_TAC[REAL_MUL_LID; REAL_OF_NUM_POW; REAL_OF_NUM_LT]];
      MATCH_MP_TAC(NORM_ARITH
       `!u. dist(w:real^N,u) < e / &2 /\ dist(z,u) < e / &2
            ==> dist(w,z) < e`) THEN
      EXISTS_TAC `(f:real^1->real^N)(c(&j / &2 pow n))` THEN
      REWRITE_TAC[dist] THEN CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
      ASM_REWRITE_TAC[]];
    ALL_TAC] THEN
  MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `h:real^1->real^N` THEN
  REWRITE_TAC[FORALL_IN_GSPEC; LIFT_DROP] THEN
  DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o CONJUNCT1)) THEN
  FIRST_ASSUM(ASSUME_TAC o MATCH_MP UNIFORMLY_CONTINUOUS_IMP_CONTINUOUS) THEN
  ONCE_REWRITE_TAC[MESON[] `h x = f(c(drop x)) <=> f(c(drop x)) = h x`] THEN
  REWRITE_TAC[IN_INTER; IMP_CONJ_ALT; FORALL_IN_GSPEC] THEN
  ASM_REWRITE_TAC[IN_UNIV; LIFT_DROP; IMP_IMP; GSYM CONJ_ASSOC] THEN
  REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; LIFT_DROP] THEN
  SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_LDIV_EQ; REAL_LT_POW2] THEN
  REWRITE_TAC[REAL_MUL_LZERO; REAL_MUL_LID] THEN
  REWRITE_TAC[REAL_OF_NUM_POW; REAL_OF_NUM_LT] THEN
  REWRITE_TAC[GSYM REAL_OF_NUM_POW] THEN DISCH_TAC THEN
  CONJ_TAC THENL
   [MATCH_MP_TAC SUBSET_ANTISYM THEN CONJ_TAC THENL
     [MP_TAC(ISPEC `interval(vec 0:real^1,vec 1)`
        closure_dyadic_rationals_in_convex_set_pos_1) THEN
      SIMP_TAC[CONVEX_INTERVAL; IN_INTERVAL_1; REAL_LT_IMP_LE; DROP_VEC;
        INTERIOR_OPEN; OPEN_INTERVAL; INTERVAL_NE_EMPTY_1; REAL_LT_01;
        CLOSURE_OPEN_INTERVAL] THEN
      DISCH_THEN(fun th ->
        GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM th]) THEN
      MATCH_MP_TAC IMAGE_CLOSURE_SUBSET THEN REPEAT CONJ_TAC THENL
       [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
          CONTINUOUS_ON_SUBSET)) THEN
        MATCH_MP_TAC CLOSURE_MINIMAL THEN REWRITE_TAC[CLOSED_INTERVAL] THEN
        MATCH_MP_TAC(SET_RULE `s SUBSET u ==> s INTER t SUBSET u`) THEN
        REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED];
        MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
        MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
        ASM_REWRITE_TAC[COMPACT_INTERVAL];
        SIMP_TAC[dyadics_in_open_unit_interval; SUBSET; FORALL_IN_IMAGE] THEN
        ASM_SIMP_TAC[FORALL_IN_GSPEC] THEN
        MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
        MATCH_MP_TAC FUN_IN_IMAGE THEN REWRITE_TAC[IN_INTERVAL_1] THEN
        ASM_MESON_TAC[REAL_LE_TRANS]];
      MATCH_MP_TAC SUBSET_TRANS THEN
      EXISTS_TAC `closure(IMAGE (h:real^1->real^N)
                                 (interval (vec 0,vec 1) INTER
        {lift (&m / &2 pow n) | m IN (:num) /\ n IN (:num)}))` THEN
      CONJ_TAC THENL
       [ALL_TAC;
        MATCH_MP_TAC CLOSURE_MINIMAL THEN
        ASM_SIMP_TAC[COMPACT_IMP_CLOSED; COMPACT_INTERVAL;
                     COMPACT_CONTINUOUS_IMAGE] THEN
        MATCH_MP_TAC IMAGE_SUBSET THEN
        MATCH_MP_TAC(SET_RULE `s SUBSET u ==> s INTER t SUBSET u`) THEN
        REWRITE_TAC[INTERVAL_OPEN_SUBSET_CLOSED]] THEN
      REWRITE_TAC[SUBSET; CLOSURE_APPROACHABLE; FORALL_IN_IMAGE] THEN
      REWRITE_TAC[dyadics_in_open_unit_interval;
                  EXISTS_IN_IMAGE; EXISTS_IN_GSPEC] THEN
      X_GEN_TAC `x:real^1` THEN DISCH_TAC THEN
      X_GEN_TAC `e:real` THEN DISCH_TAC THEN UNDISCH_TAC
       `(f:real^1->real^N) continuous_on interval [vec 0,vec 1]` THEN
      DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
        COMPACT_UNIFORMLY_CONTINUOUS)) THEN
      REWRITE_TAC[COMPACT_INTERVAL; uniformly_continuous_on] THEN
      DISCH_THEN(MP_TAC o SPEC `e:real`) THEN ASM_REWRITE_TAC[] THEN
      DISCH_THEN(X_CHOOSE_THEN `d:real` STRIP_ASSUME_TAC) THEN
      SUBGOAL_THEN
       `!n. ~(n = 0)
            ==> ?m y. ODD m /\ 0 < m /\ m < 2 EXP n /\
                      y IN interval[a(&m / &2 pow n),b(&m / &2 pow n)] /\
                     (f:real^1->real^N) y = f x`
      MP_TAC THENL
       [ALL_TAC;
        MP_TAC(SPECL [`inv(&2)`; `min (d / &2) (&1 / &4)`]
         REAL_ARCH_POW_INV) THEN
        ASM_REWRITE_TAC[REAL_HALF; REAL_POW_INV; REAL_LT_MIN] THEN
        CONV_TAC REAL_RAT_REDUCE_CONV THEN
        DISCH_THEN(X_CHOOSE_THEN `n:num` MP_TAC) THEN
        ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THEN
        CONV_TAC REAL_RAT_REDUCE_CONV THEN STRIP_TAC THEN
        DISCH_THEN(MP_TAC o SPEC `n:num`) THEN ASM_REWRITE_TAC[] THEN
        MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `m:num` THEN
        DISCH_THEN(X_CHOOSE_THEN `y:real^1` MP_TAC) THEN
        REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
        DISCH_THEN(SUBST1_TAC o SYM) THEN EXISTS_TAC `n:num` THEN
        ASM_SIMP_TAC[] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
        RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN
        REWRITE_TAC[DIST_REAL; GSYM drop; IN_INTERVAL_1] THEN
        REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC]) THEN
        FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
         `a <= y /\ y <= b
          ==> a <= c /\ c <= b /\ abs(a - b) < d
              ==> abs(c - y) < d`)) THEN
        REPEAT(CONJ_TAC THENL [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC]) THEN
        MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `&2 / &2 pow n` THEN
        ASM_SIMP_TAC[] THEN ASM_REAL_ARITH_TAC] THEN
      MATCH_MP_TAC num_INDUCTION THEN REWRITE_TAC[NOT_SUC] THEN
      X_GEN_TAC `n:num` THEN ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THENL
       [EXISTS_TAC `1` THEN CONV_TAC NUM_REDUCE_CONV THEN
        ASM_REWRITE_TAC[REAL_POW_1] THEN
        SUBGOAL_THEN
         `x IN interval[vec 0:real^1,u] \/
          x IN interval[u,v] \/
          x IN interval[v,vec 1]`
        STRIP_ASSUME_TAC THENL
         [REWRITE_TAC[IN_INTERVAL_1] THEN
          RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN
          ASM_REAL_ARITH_TAC;
          EXISTS_TAC `u:real^1` THEN
          ASM_MESON_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY_1];
          EXISTS_TAC `x:real^1` THEN ASM_MESON_TAC[];
          EXISTS_TAC `v:real^1` THEN
          ASM_MESON_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY_1]];
        DISCH_THEN(X_CHOOSE_THEN `m:num`
         (X_CHOOSE_THEN `y:real^1` MP_TAC)) THEN
        REPLICATE_TAC 3 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
        DISCH_THEN(CONJUNCTS_THEN2 MP_TAC (SUBST1_TAC o SYM)) THEN
        FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
        DISCH_THEN(X_CHOOSE_THEN `j:num` SUBST_ALL_TAC) THEN
        REWRITE_TAC[ADD1] THEN DISCH_TAC THEN
        SUBGOAL_THEN
        `y IN interval[a(&(2 * j + 1) / &2 pow n):real^1,
                       b(&(4 * j + 1) / &2 pow (n + 1))] \/
         y IN interval[b(&(4 * j + 1) / &2 pow (n + 1)),
                       a(&(4 * j + 3) / &2 pow (n + 1))] \/
         y IN interval[a(&(4 * j + 3) / &2 pow (n + 1)),
                       b(&(2 * j + 1) / &2 pow n)]`
        STRIP_ASSUME_TAC THENL
         [REWRITE_TAC[IN_INTERVAL_1] THEN
          RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN
          ASM_REAL_ARITH_TAC;
          EXISTS_TAC `4 * j + 1` THEN
          EXISTS_TAC `y:real^1` THEN
          REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH; EXP_ADD] THEN
          REPEAT(CONJ_TAC THENL [ASM_ARITH_TAC; ALL_TAC]) THEN
          FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
           `y IN interval[a,b]
            ==> a = a' /\ b = b' ==> y IN interval[a',b']`)) THEN
          ASM_MESON_TAC[LE_1];
          EXISTS_TAC `4 * j + 1` THEN
          EXISTS_TAC `b(&(4 * j + 1) / &2 pow (n + 1)):real^1` THEN
          REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH; EXP_ADD] THEN
          REPEAT(CONJ_TAC THENL [ASM_ARITH_TAC; ALL_TAC]) THEN
          REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY_1] THEN
          CONJ_TAC THENL [ASM_MESON_TAC[REAL_LE_TRANS]; ALL_TAC] THEN
          FIRST_X_ASSUM(MP_TAC o SPECL
           [`a(&(2 * j + 1) / &2 pow n):real^1`;
            `b(&(2 * j + 1) / &2 pow n):real^1`;
            `c(&(2 * j + 1) / &2 pow n):real^1`]) THEN
          ANTS_TAC THENL
           [ASM_REWRITE_TAC[midpoint; IN_INTERVAL_1; SUBSET_INTERVAL_1];
            REPLICATE_TAC 4
             (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
            DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC)] THEN
          MATCH_MP_TAC(MESON[]
           `a IN s /\ b IN s ==> (!x. x IN s ==> f x = k) ==> f a = f b`) THEN
          SUBGOAL_THEN
           `leftcut (a (&(2 * j + 1) / &2 pow n))
                    (b (&(2 * j + 1) / &2 pow n))
                    (c (&(2 * j + 1) / &2 pow n):real^1):real^1 =
            b(&(4 * j + 1) / &2 pow (n + 1)) /\
            rightcut (a (&(2 * j + 1) / &2 pow n))
                     (b (&(2 * j + 1) / &2 pow n))
                     (c (&(2 * j + 1) / &2 pow n)):real^1 =
            a(&(4 * j + 3) / &2 pow (n + 1))`
          (CONJUNCTS_THEN SUBST_ALL_TAC) THENL
            [ASM_MESON_TAC[LE_1]; ALL_TAC] THEN
          REWRITE_TAC[ENDS_IN_INTERVAL; INTERVAL_NE_EMPTY_1] THEN
          CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
          FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
           `y IN interval[a,b]
            ==> a = a' /\ b = b' ==> y IN interval[a',b']`)) THEN
          ASM_MESON_TAC[LE_1];
          EXISTS_TAC `4 * j + 3` THEN
          EXISTS_TAC `y:real^1` THEN
          REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH; EXP_ADD] THEN
          REPEAT(CONJ_TAC THENL [ASM_ARITH_TAC; ALL_TAC]) THEN
          FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (MESON[]
           `y IN interval[a,b]
            ==> a = a' /\ b = b' ==> y IN interval[a',b']`)) THEN
          ASM_MESON_TAC[LE_1]]]];
    ALL_TAC] THEN
  SUBGOAL_THEN
   `!n m. drop(a(&m / &2 pow n)) < drop(b(&m / &2 pow n)) /\
          (!x. drop(a(&m / &2 pow n)) < drop x /\
               drop x <= drop(b(&m / &2 pow n))
               ==> ~(f x = f(a(&m / &2 pow n)))) /\
          (!x. drop(a(&m / &2 pow n)) <= drop x /\
               drop x < drop(b(&m / &2 pow n))
               ==> ~(f x :real^N = f(b(&m / &2 pow n))))`
  ASSUME_TAC THENL
   [SUBGOAL_THEN `drop u < drop v` ASSUME_TAC THENL
     [ASM_REWRITE_TAC[REAL_LT_LE; DROP_EQ] THEN DISCH_THEN SUBST_ALL_TAC THEN
      RULE_ASSUM_TAC(REWRITE_RULE
       [IN_DELETE; IN_INTERVAL_1; GSYM DROP_EQ; DROP_VEC]) THEN
      ASM_MESON_TAC[DROP_EQ];
      ALL_TAC] THEN
    SUBGOAL_THEN
     `(!x. drop u < drop x /\ drop x <= drop v
          ==> ~((f:real^1->real^N) x = f u)) /\
      (!x. drop u <= drop x /\ drop x < drop v
           ==> ~(f x = f v))`
    STRIP_ASSUME_TAC THENL
     [SUBGOAL_THEN
       `(f:real^1->real^N) u = f(vec 0) /\
        (f:real^1->real^N) v = f(vec 1)`
       (CONJUNCTS_THEN SUBST1_TAC)
      THENL
       [CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
        ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL];
        ALL_TAC] THEN
      CONJ_TAC THEN GEN_TAC THEN STRIP_TAC THEN
      FIRST_X_ASSUM MATCH_MP_TAC THEN
      ASM_REWRITE_TAC[IN_DELETE; IN_INTERVAL_1; GSYM DROP_EQ] THEN
      ASM_REAL_ARITH_TAC;
      ALL_TAC] THEN
    MATCH_MP_TAC num_INDUCTION THEN
    ASM_REWRITE_TAC[REAL_ARITH `&m / &2 pow 0 = (&2 * &m) / &2`] THEN
    ASM_REWRITE_TAC[REAL_OF_NUM_MUL] THEN
    X_GEN_TAC `n:num` THEN DISCH_THEN(LABEL_TAC "*") THEN
    DISJ_CASES_TAC(ARITH_RULE `n = 0 \/ 0 < n`) THEN
    ASM_REWRITE_TAC[ARITH; REAL_POW_1] THEN
    X_GEN_TAC `j:num` THEN
    DISJ_CASES_TAC(ISPEC `j:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `k:num` SUBST1_TAC) THEN
      SIMP_TAC[GSYM REAL_OF_NUM_MUL; real_div; REAL_INV_MUL; real_pow] THEN
      ASM_REWRITE_TAC[REAL_ARITH `(&2 * p) * inv(&2) * inv q = p / q`];
      ALL_TAC] THEN
    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
    DISCH_THEN(X_CHOOSE_THEN `k:num` SUBST1_TAC) THEN
    DISJ_CASES_TAC(ISPEC `k:num` EVEN_OR_ODD) THENL
     [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [EVEN_EXISTS]) THEN
      DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN
      ASM_SIMP_TAC[ARITH_RULE `2 * 2 * m = 4 * m`; ADD1] THEN
      FIRST_X_ASSUM(MP_TAC o SPECL
       [`a(&(2 * m + 1) / &2 pow n):real^1`;
        `b(&(2 * m + 1) / &2 pow n):real^1`;
        `c(&(2 * m + 1) / &2 pow n):real^1`]) THEN
      ANTS_TAC THENL
       [REWRITE_TAC[IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
        ASM_MESON_TAC[REAL_LE_TRANS];
        REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
        DISCH_THEN(K ALL_TAC)] THEN
      SUBGOAL_THEN
       `(f:real^1->real^N)
        (leftcut (a (&(2 * m + 1) / &2 pow n):real^1)
                 (b (&(2 * m + 1) / &2 pow n):real^1)
                 (c (&(2 * m + 1) / &2 pow n):real^1)) =
        (f:real^1->real^N) (c(&(2 * m + 1) / &2 pow n))`
      ASSUME_TAC THENL
       [FIRST_X_ASSUM MATCH_MP_TAC THEN
        ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL] THEN ASM_REAL_ARITH_TAC;
        ASM_REWRITE_TAC[]] THEN
      GEN_REWRITE_TAC LAND_CONV [REAL_LT_LE] THEN ASM_REWRITE_TAC[DROP_EQ] THEN
      REPEAT CONJ_TAC THENL
       [DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
        UNDISCH_THEN
         `(f:real^1->real^N) (a (&(2 * m + 1) / &2 pow n)) =
          f(c (&(2 * m + 1) / &2 pow n))` (MP_TAC o SYM) THEN
        REWRITE_TAC[] THEN
        FIRST_ASSUM(MATCH_MP_TAC o CONJUNCT1 o CONJUNCT2 o SPEC_ALL) THEN
        REWRITE_TAC[GSYM(ASSUME `!x. midpoint ((a:real->real^1) x,b x) = c x`);
                    midpoint; DROP_CMUL; DROP_ADD] THEN
        ASM_REWRITE_TAC[REAL_ARITH
         `a < inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a < b`];
        GEN_TAC THEN STRIP_TAC THEN
        FIRST_ASSUM(MATCH_MP_TAC o CONJUNCT1 o CONJUNCT2 o SPEC_ALL) THEN
        ASM_MESON_TAC[REAL_LE_TRANS];
        GEN_TAC THEN STRIP_TAC THEN FIRST_X_ASSUM
         (fun th -> MATCH_MP_TAC th THEN
                    REWRITE_TAC[IN_INTERVAL_1; IN_DELETE; GSYM DROP_EQ] THEN
             GEN_REWRITE_TAC I [REAL_ARITH
              `(a <= x /\ x <= b) /\ ~(x = b) <=> a <= x /\ x < b`]) THEN
        ASM_REWRITE_TAC[]];
       FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
       DISCH_THEN(X_CHOOSE_THEN `m:num` SUBST1_TAC) THEN
       ASM_SIMP_TAC[ARITH_RULE `2 * (2 * m + 1) + 1  = 4 * m + 3`; ADD1] THEN
       FIRST_X_ASSUM(MP_TAC o SPECL
        [`a(&(2 * m + 1) / &2 pow n):real^1`;
         `b(&(2 * m + 1) / &2 pow n):real^1`;
         `c(&(2 * m + 1) / &2 pow n):real^1`]) THEN
      ANTS_TAC THENL
       [REWRITE_TAC[IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
        ASM_MESON_TAC[REAL_LE_TRANS];
        REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
        DISCH_THEN(K ALL_TAC)] THEN
      SUBGOAL_THEN
       `(f:real^1->real^N)
        (rightcut (a (&(2 * m + 1) / &2 pow n):real^1)
                  (b (&(2 * m + 1) / &2 pow n):real^1)
                  (c (&(2 * m + 1) / &2 pow n):real^1)) =
        (f:real^1->real^N) (c(&(2 * m + 1) / &2 pow n))`
      ASSUME_TAC THENL
       [FIRST_X_ASSUM MATCH_MP_TAC THEN
        ASM_REWRITE_TAC[IN_INTERVAL_1; REAL_LE_REFL] THEN ASM_REAL_ARITH_TAC;
        ASM_REWRITE_TAC[]] THEN
      GEN_REWRITE_TAC LAND_CONV [REAL_LT_LE] THEN ASM_REWRITE_TAC[DROP_EQ] THEN
      REPEAT CONJ_TAC THENL
       [DISCH_THEN SUBST_ALL_TAC THEN
        UNDISCH_THEN
         `(f:real^1->real^N) (b (&(2 * m + 1) / &2 pow n)) =
          f(c (&(2 * m + 1) / &2 pow n))` (MP_TAC o SYM) THEN
        REWRITE_TAC[] THEN
        FIRST_ASSUM(MATCH_MP_TAC o CONJUNCT2 o CONJUNCT2 o SPEC_ALL) THEN
        REWRITE_TAC[GSYM(ASSUME `!x. midpoint ((a:real->real^1) x,b x) = c x`);
                    midpoint; DROP_CMUL; DROP_ADD] THEN
        ASM_REWRITE_TAC[REAL_ARITH
         `a <= inv(&2) * (a + b) /\ inv(&2) * (a + b) < b <=> a < b`];
        GEN_TAC THEN STRIP_TAC THEN FIRST_X_ASSUM
         (fun th -> MATCH_MP_TAC th THEN
                    REWRITE_TAC[IN_INTERVAL_1; IN_DELETE; GSYM DROP_EQ] THEN
             GEN_REWRITE_TAC I [REAL_ARITH
              `(a <= x /\ x <= b) /\ ~(x = a) <=> a < x /\ x <= b`]) THEN
        ASM_REWRITE_TAC[];
        GEN_TAC THEN STRIP_TAC THEN
        FIRST_ASSUM(MATCH_MP_TAC o CONJUNCT2 o CONJUNCT2 o SPEC_ALL) THEN
        ASM_MESON_TAC[REAL_LE_TRANS]]];
    ALL_TAC] THEN
  SUBGOAL_THEN
   `!m i n j. 0 < i /\ i < 2 EXP m /\ 0 < j /\ j < 2 EXP n /\
              &i / &2 pow m < &j / &2 pow n
              ==> drop(c(&i / &2 pow m)) <= drop(c(&j / &2 pow n))`
  ASSUME_TAC THENL
   [SUBGOAL_THEN
     `!N m p i k.
         0 < i /\ i < 2 EXP m /\ 0 < k /\ k < 2 EXP p /\
         &i / &2 pow m < &k / &2 pow p /\ m + p = N
         ==> ?j n. ODD(j) /\ ~(n = 0) /\
                   &i / &2 pow m <= &j / &2 pow n /\
                   &j / &2 pow n <= &k / &2 pow p /\
                   abs(&i / &2 pow m - &j / &2 pow n) < inv(&2 pow n) /\
                   abs(&k / &2 pow p - &j / &2 pow n) < inv(&2 pow n)`
    MP_TAC THENL
     [MATCH_MP_TAC num_WF THEN X_GEN_TAC `N:num` THEN
      DISCH_THEN(LABEL_TAC "I") THEN
      MAP_EVERY X_GEN_TAC [`m:num`; `p:num`; `i:num`; `k:num`] THEN
      STRIP_TAC THEN
      SUBGOAL_THEN
       `&i / &2 pow m <= &1 / &2 pow 1 /\
        &1 / &2 pow 1 <= &k / &2 pow p \/
        &k / &2 pow p < &1 / &2 \/
        &1 / &2 < &i / &2 pow m`
       (REPEAT_TCL DISJ_CASES_THEN STRIP_ASSUME_TAC)
      THENL
       [ASM_REAL_ARITH_TAC;
        MAP_EVERY EXISTS_TAC [`1`; `1`] THEN ASM_REWRITE_TAC[ARITH] THEN
        MATCH_MP_TAC(REAL_ARITH
         `&0 < i /\ i <= &1 / &2 pow 1 /\ &1 / &2 pow 1 <= k /\ k < &1
          ==> abs(i -  &1 / &2 pow 1) < inv(&2 pow 1) /\
              abs(k -  &1 / &2 pow 1) < inv(&2 pow 1)`) THEN
        ASM_SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_LDIV_EQ; REAL_LT_POW2] THEN
        REWRITE_TAC[MULT_CLAUSES; REAL_OF_NUM_POW; REAL_OF_NUM_MUL] THEN
        ASM_REWRITE_TAC[REAL_OF_NUM_LT];
        REMOVE_THEN "I" MP_TAC THEN
        POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
        SPEC_TAC(`m:num`,`m:num`) THEN INDUCT_TAC THEN
        REWRITE_TAC[ARITH_RULE `i < 2 EXP 0 <=> ~(0 < i)`] THEN
        REWRITE_TAC[TAUT `p /\ ~p /\ q <=> F`] THEN POP_ASSUM(K ALL_TAC) THEN
        SPEC_TAC(`p:num`,`p:num`) THEN INDUCT_TAC THEN
        REWRITE_TAC[ARITH_RULE `i < 2 EXP 0 <=> ~(0 < i)`] THEN
        REWRITE_TAC[TAUT `p /\ ~p /\ q <=> F`] THEN POP_ASSUM(K ALL_TAC) THEN
        STRIP_TAC THEN DISCH_THEN(MP_TAC o SPEC `m + p:num`) THEN
        ANTS_TAC THENL [EXPAND_TAC "N" THEN ARITH_TAC; ALL_TAC] THEN
        DISCH_THEN(MP_TAC o SPECL [`m:num`; `p:num`; `i:num`; `k:num`]) THEN
        ASM_REWRITE_TAC[] THEN ANTS_TAC THENL
         [MAP_EVERY UNDISCH_TAC
           [`&k / &2 pow SUC p < &1 / &2`;
            `&i / &2 pow SUC m < &k / &2 pow SUC p`] THEN
          REWRITE_TAC[real_div; real_pow; REAL_INV_MUL;
                      REAL_ARITH `x * inv(&2) * y = (x * y) * inv(&2)`] THEN
          SIMP_TAC[GSYM real_div; REAL_LT_DIV2_EQ; REAL_OF_NUM_LT; ARITH] THEN
          REWRITE_TAC[IMP_IMP] THEN DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
           `x < y /\ y < &1 ==> x < &1 /\ y < &1`)) THEN
          SIMP_TAC[REAL_LT_LDIV_EQ; REAL_LT_POW2; REAL_MUL_LID] THEN
          REWRITE_TAC[REAL_OF_NUM_POW; REAL_OF_NUM_LT];
          MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `j:num` THEN
          DISCH_THEN(X_CHOOSE_THEN `n:num` STRIP_ASSUME_TAC) THEN
          EXISTS_TAC `SUC n` THEN ASM_REWRITE_TAC[NOT_SUC] THEN
          REWRITE_TAC[real_div; real_pow; REAL_INV_MUL;
                      REAL_ARITH `inv(&2) * y = y * inv(&2)`] THEN
          REWRITE_TAC[GSYM REAL_SUB_RDISTRIB; REAL_MUL_ASSOC;
                      REAL_ABS_MUL; REAL_ABS_INV; REAL_ABS_NUM] THEN
          REWRITE_TAC[GSYM real_div; REAL_ABS_NUM] THEN
          ASM_SIMP_TAC[REAL_LT_DIV2_EQ; REAL_LE_DIV2_EQ;
                       REAL_OF_NUM_LT; ARITH]];
        REMOVE_THEN "I" MP_TAC THEN
        POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN
        SPEC_TAC(`m:num`,`m:num`) THEN INDUCT_TAC THEN
        REWRITE_TAC[ARITH_RULE `i < 2 EXP 0 <=> ~(0 < i)`] THEN
        REWRITE_TAC[TAUT `p /\ ~p /\ q <=> F`] THEN POP_ASSUM(K ALL_TAC) THEN
        SPEC_TAC(`p:num`,`p:num`) THEN INDUCT_TAC THEN
        REWRITE_TAC[ARITH_RULE `i < 2 EXP 0 <=> ~(0 < i)`] THEN
        REWRITE_TAC[TAUT `p /\ ~p /\ q <=> F`] THEN POP_ASSUM(K ALL_TAC) THEN
        STRIP_TAC THEN DISCH_THEN(MP_TAC o SPEC `m + p:num`) THEN
        ANTS_TAC THENL [EXPAND_TAC "N" THEN ARITH_TAC; ALL_TAC] THEN
        DISCH_THEN(MP_TAC o SPECL
         [`m:num`; `p:num`; `i - 2 EXP m`; `k - 2 EXP p`]) THEN
        ASM_REWRITE_TAC[] THEN
        MAP_EVERY UNDISCH_TAC
         [`&1 / &2 < &i / &2 pow SUC m`;
          `&i / &2 pow SUC m < &k / &2 pow SUC p`] THEN
        REWRITE_TAC[real_div; real_pow; REAL_INV_MUL;
                    REAL_ARITH `x * inv(&2) * y = (x * y) * inv(&2)`] THEN
        SIMP_TAC[GSYM real_div; REAL_LT_DIV2_EQ; REAL_OF_NUM_LT; ARITH] THEN
        GEN_REWRITE_TAC I [IMP_IMP] THEN DISCH_THEN(fun th ->
          STRIP_ASSUME_TAC th THEN MP_TAC(MATCH_MP
           (REAL_ARITH `i < k /\ &1 < i ==> &1 < i /\ &1 < k`) th)) THEN
        SIMP_TAC[REAL_LT_RDIV_EQ; REAL_LT_POW2; REAL_MUL_LID] THEN
        GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [REAL_OF_NUM_POW] THEN
        SIMP_TAC[REAL_OF_NUM_LT; GSYM REAL_OF_NUM_SUB; LT_IMP_LE] THEN
        STRIP_TAC THEN REWRITE_TAC[GSYM REAL_OF_NUM_POW] THEN ANTS_TAC THENL
         [ASM_SIMP_TAC[ARITH_RULE `a < b ==> 0 < b - a`] THEN
          ASM_SIMP_TAC[GSYM REAL_LT_RDIV_EQ; REAL_LT_POW2] THEN
          REWRITE_TAC[real_div; REAL_SUB_RDISTRIB] THEN
          ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ; REAL_LT_POW2] THEN
          ASM_REWRITE_TAC[REAL_ARITH `u * inv v - &1 < w * inv z - &1 <=>
                                      u / v < w / z`] THEN
          CONJ_TAC THEN MATCH_MP_TAC(ARITH_RULE
           `i < 2 * m ==> i - m < m`) THEN
          ASM_REWRITE_TAC[GSYM(CONJUNCT2 EXP)];
          REWRITE_TAC[real_div; REAL_SUB_RDISTRIB] THEN
          ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ; REAL_LT_POW2] THEN
          REWRITE_TAC[GSYM real_div] THEN
          DISCH_THEN(X_CHOOSE_THEN `j:num` (X_CHOOSE_THEN `n:num`
           STRIP_ASSUME_TAC)) THEN
          EXISTS_TAC `2 EXP n + j` THEN EXISTS_TAC `SUC n` THEN
          ASM_REWRITE_TAC[NOT_SUC; ODD_ADD; ODD_EXP; ARITH] THEN
          REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_POW] THEN
          REWRITE_TAC[real_div; real_pow; REAL_INV_MUL;
                      REAL_ARITH `inv(&2) * y = y * inv(&2)`] THEN
          REWRITE_TAC[GSYM REAL_SUB_RDISTRIB; REAL_MUL_ASSOC;
                      REAL_ABS_MUL; REAL_ABS_INV; REAL_ABS_NUM] THEN
          REWRITE_TAC[GSYM real_div; REAL_ABS_NUM] THEN
          ASM_SIMP_TAC[REAL_LT_DIV2_EQ; REAL_LE_DIV2_EQ;
                       REAL_OF_NUM_LT; ARITH] THEN
          REWRITE_TAC[real_div; REAL_ADD_RDISTRIB] THEN
          ASM_SIMP_TAC[REAL_MUL_RINV; REAL_LT_IMP_NZ; REAL_LT_POW2] THEN
          REWRITE_TAC[GSYM real_div] THEN ASM_REAL_ARITH_TAC]];
      DISCH_THEN(fun th ->
       MAP_EVERY X_GEN_TAC [`m:num`; `i:num`; `p:num`; `k:num`] THEN
       STRIP_TAC THEN MP_TAC(ISPECL
        [`m + p:num`; `m:num`; `p:num`; `i:num`; `k:num`] th)) THEN
      ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
      MAP_EVERY X_GEN_TAC [`j:num`; `n:num`] THEN STRIP_TAC THEN
      FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
      REWRITE_TAC[ADD1; LEFT_IMP_EXISTS_THM] THEN
      X_GEN_TAC `q:num` THEN DISCH_THEN SUBST_ALL_TAC THEN
      MATCH_MP_TAC REAL_LE_TRANS THEN
      EXISTS_TAC `drop(c(&(2 * q + 1) / &2 pow n))` THEN CONJ_TAC THENL
       [ASM_CASES_TAC `&i / &2 pow m = &(2 * q + 1) / &2 pow n` THEN
        ASM_REWRITE_TAC[REAL_LE_REFL] THEN
        SUBGOAL_THEN
         `drop(a(&(4 * q + 1) / &2 pow (n + 1))) <= drop(c(&i / &2 pow m)) /\
          drop(c(&i / &2 pow m)) <= drop(b(&(4 * q + 1) / &2 pow (n + 1)))`
        MP_TAC THENL
         [FIRST_X_ASSUM MATCH_MP_TAC THEN
          REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH] THEN
          SIMP_TAC[real_div; REAL_POW_ADD; REAL_INV_MUL; REAL_MUL_ASSOC] THEN
          REWRITE_TAC[GSYM real_div; REAL_POW_1] THEN
          FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
           `abs(i - q) < n
            ==> i <= q /\ ~(i = q) /\ q = q' + n / &2
                ==> abs(i - q') < n / &2`)) THEN
          ASM_REWRITE_TAC[] THEN
          REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
          REAL_ARITH_TAC;
          ASM_SIMP_TAC[LE_1] THEN MATCH_MP_TAC(REAL_ARITH
           `l <= d ==> u <= v /\ c <= l ==> c <= d`) THEN
          FIRST_X_ASSUM(MP_TAC o SPECL
           [`a(&(2 * q + 1) / &2 pow n):real^1`;
            `b(&(2 * q + 1) / &2 pow n):real^1`;
            `c(&(2 * q + 1) / &2 pow n):real^1`]) THEN
          ANTS_TAC THENL
           [REWRITE_TAC[IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
            ASM_MESON_TAC[REAL_LE_TRANS];
            DISCH_THEN(fun th -> REWRITE_TAC[th])]];
        ASM_CASES_TAC `&k / &2 pow p = &(2 * q + 1) / &2 pow n` THEN
        ASM_REWRITE_TAC[REAL_LE_REFL] THEN
        SUBGOAL_THEN
         `drop(a(&(4 * q + 3) / &2 pow (n + 1))) <= drop(c(&k / &2 pow p)) /\
          drop(c(&k / &2 pow p)) <= drop(b(&(4 * q + 3) / &2 pow (n + 1)))`
        MP_TAC THENL
         [FIRST_X_ASSUM MATCH_MP_TAC THEN
          REWRITE_TAC[ODD_ADD; ODD_MULT; ARITH] THEN
          SIMP_TAC[real_div; REAL_POW_ADD; REAL_INV_MUL; REAL_MUL_ASSOC] THEN
          REWRITE_TAC[GSYM real_div; REAL_POW_1] THEN
          FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
           `abs(i - q) < n
            ==> q <= i /\ ~(i = q) /\ q' = q +  n / &2
                ==> abs(i - q') < n / &2`)) THEN
          ASM_REWRITE_TAC[] THEN
          REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
          REAL_ARITH_TAC;
          ASM_SIMP_TAC[LE_1] THEN MATCH_MP_TAC(REAL_ARITH
           `d <= l ==> l <= c /\ u <= v ==> d <= c`) THEN
          FIRST_X_ASSUM(MP_TAC o SPECL
           [`a(&(2 * q + 1) / &2 pow n):real^1`;
            `b(&(2 * q + 1) / &2 pow n):real^1`;
            `c(&(2 * q + 1) / &2 pow n):real^1`]) THEN
          ANTS_TAC THENL
           [REWRITE_TAC[IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
            ASM_MESON_TAC[REAL_LE_TRANS];
            DISCH_THEN(fun th -> REWRITE_TAC[th])]]]];
    ALL_TAC] THEN
  REWRITE_TAC[FORALL_LIFT] THEN MATCH_MP_TAC REAL_WLOG_LT THEN
  REWRITE_TAC[] THEN CONJ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
  REWRITE_TAC[FORALL_DROP; LIFT_DROP; IN_INTERVAL_1; DROP_VEC] THEN
  MAP_EVERY X_GEN_TAC [`x1:real^1`; `x2:real^1`] THEN REPEAT STRIP_TAC THEN
  SUBGOAL_THEN
   `?m n. 0 < m /\ m < 2 EXP n /\
          drop x1 < &m / &2 pow n /\ &m / &2 pow n < drop x2 /\
          ~(h(x1):real^N = h(lift(&m / &2 pow n)))`
  STRIP_ASSUME_TAC THENL
   [MP_TAC(ISPEC `interval(vec 0:real^1,vec 1)`
        closure_dyadic_rationals_in_convex_set_pos_1) THEN
    SIMP_TAC[CONVEX_INTERVAL; IN_INTERVAL_1; REAL_LT_IMP_LE; DROP_VEC;
            INTERIOR_OPEN; OPEN_INTERVAL; INTERVAL_NE_EMPTY_1; REAL_LT_01;
            CLOSURE_OPEN_INTERVAL] THEN
    REWRITE_TAC[EXTENSION] THEN
    DISCH_THEN(MP_TAC o SPEC `inv(&2) % (x1 + x2):real^1`) THEN
    REWRITE_TAC[dyadics_in_open_unit_interval; IN_INTERVAL_1; DROP_VEC] THEN
    REWRITE_TAC[DROP_CMUL; DROP_ADD] THEN
    MATCH_MP_TAC(TAUT `p /\ (q ==> r) ==> (q <=> p) ==> r`) THEN
    CONJ_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[CLOSURE_APPROACHABLE]] THEN
    DISCH_THEN(MP_TAC o SPEC `(drop x2 - drop x1) / &64`) THEN
    ANTS_TAC THENL [ASM_REAL_ARITH_TAC; REWRITE_TAC[EXISTS_IN_GSPEC]] THEN
    REWRITE_TAC[DIST_REAL; GSYM drop; LIFT_DROP; DROP_CMUL; DROP_ADD] THEN
    DISCH_TAC THEN
    SUBGOAL_THEN
     `?m n. (0 < m /\ m < 2 EXP n) /\
            abs(&m / &2 pow n - inv (&2) * (drop x1 + drop x2)) <
            (drop x2 - drop x1) / &64 /\
            inv(&2 pow n) < (drop x2 - drop x1) / &128`
    STRIP_ASSUME_TAC THENL
     [MP_TAC(ISPECL [`inv(&2)`; `min (&1 / &4) ((drop x2 - drop x1) / &128)`]
      REAL_ARCH_POW_INV) THEN ANTS_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
      DISCH_THEN(X_CHOOSE_THEN `N:num` MP_TAC) THEN
      ASM_CASES_TAC `N = 0` THENL
       [ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC; ALL_TAC] THEN
      REWRITE_TAC[REAL_INV_POW; REAL_LT_MIN; EXISTS_IN_GSPEC] THEN
      STRIP_TAC THEN
      FIRST_X_ASSUM(X_CHOOSE_THEN `m:num` (X_CHOOSE_THEN `n:num`
        STRIP_ASSUME_TAC)) THEN
      EXISTS_TAC `2 EXP N * m` THEN EXISTS_TAC `N + n:num` THEN
      ASM_SIMP_TAC[EXP_ADD; LT_MULT; EXP_LT_0; LT_MULT_LCANCEL; LE_1;
                   ARITH_EQ] THEN
      CONJ_TAC THENL
       [REWRITE_TAC[REAL_POW_ADD; real_div; REAL_INV_MUL] THEN
        REWRITE_TAC[GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_POW; REAL_ARITH
         `(N * n) * inv N * inv m:real = (N / N) * (n / m)`] THEN
        ASM_SIMP_TAC[REAL_DIV_REFL; REAL_POW_EQ_0; REAL_OF_NUM_EQ; ARITH_EQ;
                     REAL_MUL_LID; GSYM real_div];
        MATCH_MP_TAC REAL_LET_TRANS THEN EXISTS_TAC `inv(&2) pow N` THEN
        ASM_REWRITE_TAC[] THEN MATCH_MP_TAC REAL_POW_MONO_INV THEN
        CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[LE_ADD]];
      REWRITE_TAC[CONJ_ASSOC] THEN MATCH_MP_TAC(MESON[]
       `!m n m' n'. (P m n /\ P m' n') /\
                    (P m n /\ P m' n' ==> ~(g m n = g m' n'))
        ==> (?m n. P m n /\ ~(a = g m n))`) THEN
      MAP_EVERY EXISTS_TAC
       [`2 * m + 1`; `n + 1`; `4 * m + 3`; `n + 2`] THEN
      CONJ_TAC THENL
       [REWRITE_TAC[EXP_ADD] THEN CONV_TAC NUM_REDUCE_CONV THEN CONJ_TAC THEN
        (REWRITE_TAC[GSYM CONJ_ASSOC] THEN
         REPLICATE_TAC 2 (CONJ_TAC THENL [ASM_ARITH_TAC; ALL_TAC])) THEN
        FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
         `abs(x - inv(&2) * (x1 + x2)) < (x2 - x1) / &64
          ==> abs(x - y) < (x2 - x1) / &4
              ==> x1 < y /\ y < x2`)) THEN
        FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REAL_ARITH
         `n < x / &128 ==> &0 < x /\ y < &4 * n ==> y < x / &4`)) THEN
        ASM_REWRITE_TAC[REAL_SUB_LT] THEN
        REWRITE_TAC[GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
        MATCH_MP_TAC(REAL_ARITH
         `a / y = x /\ abs(b / y) < z
          ==> abs(x - (a + b) / y) < z`) THEN
        ONCE_REWRITE_TAC[ADD_SYM] THEN REWRITE_TAC[REAL_POW_ADD] THEN
        SIMP_TAC[REAL_ABS_DIV; REAL_ABS_NUM; REAL_ABS_MUL; REAL_ABS_POW] THEN
        REWRITE_TAC[real_div; REAL_INV_MUL; REAL_MUL_ASSOC] THEN
        SIMP_TAC[REAL_LT_RMUL_EQ; REAL_EQ_MUL_RCANCEL; REAL_LT_INV_EQ;
           REAL_LT_POW2; REAL_INV_EQ_0; REAL_POW_EQ_0; ARITH_EQ;
           REAL_OF_NUM_EQ] THEN
        CONV_TAC REAL_RAT_REDUCE_CONV THEN REAL_ARITH_TAC;
        ASM_SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN
        FIRST_X_ASSUM(MP_TAC o CONJUNCT1 o SPECL [`n + 2`; `4 * m + 3`]) THEN
        UNDISCH_THEN `!x. midpoint ((a:real->real^1) x,b x) = c x`
         (fun th -> REWRITE_TAC[GSYM th] THEN
              ASM_SIMP_TAC[ARITH_RULE `n + 2 = (n + 1) + 1 /\ 0 < n + 1`] THEN
              REWRITE_TAC[th] THEN ASSUME_TAC th) THEN
        DISCH_TAC THEN
        CONV_TAC(RAND_CONV SYM_CONV) THEN
        FIRST_X_ASSUM(MP_TAC o SPECL
         [`a(&(2 * m + 1) / &2 pow (n + 1)):real^1`;
          `b(&(2 * m + 1) / &2 pow (n + 1)):real^1`;
          `c(&(2 * m + 1) / &2 pow (n + 1)):real^1`]) THEN
        ANTS_TAC THENL
         [REWRITE_TAC[IN_INTERVAL_1; SUBSET_INTERVAL_1] THEN
          ASM_MESON_TAC[REAL_LE_TRANS];
          REPLICATE_TAC 6 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
          DISCH_THEN(MATCH_MP_TAC o CONJUNCT1)] THEN
        REWRITE_TAC[IN_INTERVAL_1; IN_DELETE; GSYM DROP_EQ] THEN
        REWRITE_TAC[REAL_ARITH
         `(a <= b /\ b <= c) /\ ~(b = a) <=> a < b /\ b <= c`] THEN
        REWRITE_TAC[midpoint; DROP_CMUL; DROP_ADD] THEN
        ASM_REWRITE_TAC[REAL_ARITH
           `a < inv(&2) * (a + b) /\ inv(&2) * (a + b) <= b <=> a < b`] THEN
        ASM_REWRITE_TAC[REAL_LT_LE]]];
    ALL_TAC] THEN
  SUBGOAL_THEN
   `IMAGE h (interval[vec 0,lift(&m / &2 pow n)]) SUBSET
    IMAGE (f:real^1->real^N) (interval[vec 0,c(&m / &2 pow n)]) /\
    IMAGE h (interval[lift(&m / &2 pow n),vec 1]) SUBSET
    IMAGE (f:real^1->real^N) (interval[c(&m / &2 pow n),vec 1])`
  MP_TAC THENL
   [MP_TAC(ISPEC `interval(lift(&m / &2 pow n),vec 1)`
      closure_dyadic_rationals_in_convex_set_pos_1) THEN
    MP_TAC(ISPEC `interval(vec 0,lift(&m / &2 pow n))`
      closure_dyadic_rationals_in_convex_set_pos_1) THEN
    SUBGOAL_THEN `&0 < &m / &2 pow n /\ &m / &2 pow n < &1`
    STRIP_ASSUME_TAC THENL
     [ASM_SIMP_TAC[REAL_LT_DIV; REAL_LT_POW2; REAL_OF_NUM_LT; REAL_LT_LDIV_EQ;
        REAL_OF_NUM_MUL; REAL_OF_NUM_LT; REAL_OF_NUM_POW; MULT_CLAUSES];
      ALL_TAC] THEN
    MATCH_MP_TAC(TAUT
     `(p1 /\ p2) /\ (q1 ==> r1) /\ (q2 ==> r2)
      ==> (p1 ==> q1) ==> (p2 ==> q2) ==> r1 /\ r2`) THEN
    ASM_SIMP_TAC[CONVEX_INTERVAL; IN_INTERVAL_1; REAL_LT_IMP_LE; DROP_VEC;
     INTERIOR_OPEN; OPEN_INTERVAL; INTERVAL_NE_EMPTY_1; REAL_LT_01;
     CLOSURE_OPEN_INTERVAL; LIFT_DROP] THEN
    CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
    CONJ_TAC THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
    (MATCH_MP_TAC IMAGE_CLOSURE_SUBSET THEN REPEAT CONJ_TAC THENL
      [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
         CONTINUOUS_ON_SUBSET)) THEN
       MATCH_MP_TAC CLOSURE_MINIMAL THEN REWRITE_TAC[CLOSED_INTERVAL] THEN
       MATCH_MP_TAC(SET_RULE `s SUBSET u ==> s INTER t SUBSET u`) THEN
       ASM_SIMP_TAC[SUBSET_INTERVAL_1; LIFT_DROP; REAL_LT_IMP_LE; DROP_VEC;
                    REAL_LE_REFL];
       MATCH_MP_TAC COMPACT_IMP_CLOSED THEN
       MATCH_MP_TAC COMPACT_CONTINUOUS_IMAGE THEN
       ASM_REWRITE_TAC[COMPACT_INTERVAL] THEN
       FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
         CONTINUOUS_ON_SUBSET)) THEN
       REWRITE_TAC[SUBSET_INTERVAL_1; REAL_LE_REFL] THEN
       ASM_MESON_TAC[REAL_LE_TRANS];
       REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
       MATCH_MP_TAC(SET_RULE
        `i SUBSET interval(vec 0,vec 1) /\
         (!x. x IN interval(vec 0,vec 1) INTER l ==> x IN i ==> P x)
         ==> !x. x IN i INTER l ==> P x`) THEN
       ASM_SIMP_TAC[SUBSET_INTERVAL_1; LIFT_DROP; DROP_VEC;
                    REAL_LT_IMP_LE; REAL_LE_REFL] THEN
       REWRITE_TAC[dyadics_in_open_unit_interval; FORALL_IN_GSPEC] THEN
       MAP_EVERY X_GEN_TAC [`k:num`; `p:num`] THEN STRIP_TAC THEN
       REWRITE_TAC[IN_INTERVAL_1; DROP_VEC; LIFT_DROP] THEN
       STRIP_TAC THEN ASM_SIMP_TAC[] THEN
       MATCH_MP_TAC FUN_IN_IMAGE THEN REWRITE_TAC[IN_INTERVAL_1] THEN
       ASM_SIMP_TAC[] THEN ASM_MESON_TAC[REAL_LE_TRANS]]);
    DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
     `IMAGE h s SUBSET t /\ IMAGE h s' SUBSET t'
      ==> !x y. x IN s /\ y IN s' ==> h(x) IN t /\ h(y) IN t'`)) THEN
    DISCH_THEN(MP_TAC o SPECL [`x1:real^1`; `x2:real^1`]) THEN
    ASM_SIMP_TAC[IN_INTERVAL_1; LIFT_DROP; DROP_VEC; REAL_LT_IMP_LE] THEN
    DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
     `a IN IMAGE f s /\ a IN IMAGE f t
      ==> ?x y. x IN s /\ y IN t /\ f x = a /\ f y = a`)) THEN
    REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
    MAP_EVERY X_GEN_TAC [`t1:real^1`; `t2:real^1`] THEN
    REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(MP_TAC o SPEC `(h:real^1->real^N) x2` o
     GEN_REWRITE_RULE BINDER_CONV [GSYM IS_INTERVAL_CONNECTED_1]) THEN
    REWRITE_TAC[IS_INTERVAL_1; IN_ELIM_THM] THEN
    DISCH_THEN(MP_TAC o SPECL
     [`t1:real^1`; `t2:real^1`; `c(&m / &2 pow n):real^1`]) THEN
    UNDISCH_TAC `~(h x1:real^N = h(lift (&m / &2 pow n)))` THEN
    ASM_SIMP_TAC[] THEN MATCH_MP_TAC(TAUT `q ==> p ==> ~q ==> r`) THEN
    ASM_REWRITE_TAC[IN_INTERVAL_1; DROP_VEC] THEN
    ASM_MESON_TAC[REAL_LE_TRANS]]);;
let PATH_CONTAINS_ARC = 
prove (`!p:real^1->real^N a b. path p /\ pathstart p = a /\ pathfinish p = b /\ ~(a = b) ==> ?q. arc q /\ path_image q SUBSET path_image p /\ pathstart q = a /\ pathfinish q = b`,
REWRITE_TAC[pathstart; pathfinish; path] THEN MAP_EVERY X_GEN_TAC [`f:real^1->real^N`; `a:real^N`; `b:real^N`] THEN STRIP_TAC THEN MP_TAC(ISPECL [`\s. s SUBSET interval[vec 0,vec 1] /\ vec 0 IN s /\ vec 1 IN s /\ (!x y. x IN s /\ y IN s /\ segment(x,y) INTER s = {} ==> (f:real^1->real^N)(x) = f(y))`; `interval[vec 0:real^1,vec 1]`] BROUWER_REDUCTION_THEOREM_GEN) THEN ASM_REWRITE_TAC[GSYM path_image; CLOSED_INTERVAL; SUBSET_REFL] THEN ANTS_TAC THENL [CONJ_TAC THENL [ALL_TAC; REWRITE_TAC[ENDS_IN_UNIT_INTERVAL] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE `s INTER i = {} ==> s SUBSET i ==> s = {}`)) THEN REWRITE_TAC[SEGMENT_EQ_EMPTY] THEN ANTS_TAC THENL [ONCE_REWRITE_TAC[segment]; MESON_TAC[]] THEN MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s DIFF i SUBSET t`) THEN ASM_MESON_TAC[CONVEX_CONTAINS_SEGMENT; CONVEX_INTERVAL]] THEN X_GEN_TAC `s:num->real^1->bool` THEN REWRITE_TAC[FORALL_AND_THM] THEN STRIP_TAC THEN CONJ_TAC THENL [REWRITE_TAC[INTERS_GSPEC; SUBSET; IN_ELIM_THM; IN_UNIV] THEN ASM SET_TAC[]; ALL_TAC] THEN REPEAT(CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN REWRITE_TAC[FORALL_LIFT] THEN MATCH_MP_TAC REAL_WLOG_LT THEN REWRITE_TAC[] THEN CONJ_TAC THENL [REWRITE_TAC[SEGMENT_SYM] THEN MESON_TAC[]; REWRITE_TAC[FORALL_DROP; LIFT_DROP]] THEN MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN REWRITE_TAC[INTERS_GSPEC; IN_UNIV; IN_ELIM_THM] THEN SIMP_TAC[SEGMENT_1; REAL_LT_IMP_LE] THEN DISCH_TAC THEN STRIP_TAC THEN MATCH_MP_TAC(TAUT `(~p ==> F) ==> p`) THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] COMPACT_UNIFORMLY_CONTINUOUS)) THEN REWRITE_TAC[COMPACT_INTERVAL; uniformly_continuous_on] THEN DISCH_THEN(MP_TAC o SPEC `norm((f:real^1->real^N) x - f y) / &2`) THEN ASM_REWRITE_TAC[REAL_HALF; NORM_POS_LT; VECTOR_SUB_EQ] THEN DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `?u v. u IN interval[vec 0,vec 1] /\ v IN interval[vec 0,vec 1] /\ norm(u - x) < e /\ norm(v - y) < e /\ (f:real^1->real^N) u = f v` STRIP_ASSUME_TAC THENL [ALL_TAC; FIRST_X_ASSUM(fun th -> MP_TAC(ISPECL [`x:real^1`; `u:real^1`] th) THEN MP_TAC(ISPECL [`y:real^1`; `v:real^1`] th)) THEN ASM_REWRITE_TAC[dist] THEN ANTS_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN MATCH_MP_TAC(TAUT `q /\ (p ==> ~r) ==> p ==> ~(q ==> r)`) THEN CONJ_TAC THENL [ASM SET_TAC[]; CONV_TAC NORM_ARITH]] THEN SUBGOAL_THEN `?w z. w IN interval(x,y) /\ z IN interval(x,y) /\ drop w < drop z /\ norm(w - x) < e /\ norm(z - y) < e` STRIP_ASSUME_TAC THENL [EXISTS_TAC `x + lift(min e (drop y - drop x) / &3)` THEN EXISTS_TAC `y - lift(min e (drop y - drop x) / &3)` THEN REWRITE_TAC[IN_INTERVAL_1; DROP_ADD; DROP_SUB; LIFT_DROP; NORM_REAL; GSYM drop] THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN MP_TAC(ISPECL [`interval[w:real^1,z]`; `{s n :real^1->bool | n IN (:num)}`] COMPACT_IMP_FIP) THEN ASM_REWRITE_TAC[COMPACT_INTERVAL; FORALL_IN_GSPEC] THEN MATCH_MP_TAC(TAUT `q /\ (~p ==> r) ==> (p ==> ~q) ==> r`) THEN CONJ_TAC THENL [REWRITE_TAC[INTERS_GSPEC; IN_UNIV] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `s INTER u = {} ==> t SUBSET s ==> t INTER u = {}`)) THEN REWRITE_TAC[SUBSET_INTERVAL_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[MESON[] `~(!x. P x /\ Q x ==> R x) <=> (?x. P x /\ Q x /\ ~R x)`] THEN ONCE_REWRITE_TAC[SIMPLE_IMAGE] THEN REWRITE_TAC[EXISTS_FINITE_SUBSET_IMAGE] THEN DISCH_THEN(X_CHOOSE_THEN `k:num->bool` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM(MP_TAC o SPEC `\n:num. n` o MATCH_MP UPPER_BOUND_FINITE_SET) THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN SUBGOAL_THEN `interval[w,z] INTER (s:num->real^1->bool) n = {}` ASSUME_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `a INTER t = {} ==> s SUBSET t ==> a INTER s = {}`)) THEN REWRITE_TAC[SUBSET; INTERS_IMAGE; IN_ELIM_THM] THEN REWRITE_TAC[SET_RULE `(!x. x IN s n ==> !i. i IN k ==> x IN s i) <=> (!i. i IN k ==> s n SUBSET s i)`] THEN SUBGOAL_THEN `!i n. i <= n ==> (s:num->real^1->bool) n SUBSET s i` (fun th -> ASM_MESON_TAC[th]) THEN MATCH_MP_TAC TRANSITIVE_STEPWISE_LE THEN ASM_REWRITE_TAC[] THEN SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `?u. u IN (s:num->real^1->bool) n /\ u IN interval[x,w] /\ (interval[u,w] DELETE u) INTER (s n) = {}` MP_TAC THENL [ASM_CASES_TAC `w IN (s:num->real^1->bool) n` THENL [EXISTS_TAC `w:real^1` THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL] THEN REWRITE_TAC[INTERVAL_SING; SET_RULE `{a} DELETE a = {}`] THEN REWRITE_TAC[INTER_EMPTY; INTERVAL_NE_EMPTY_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN MP_TAC(ISPECL [`(s:num->real^1->bool) n INTER interval[x,w]`; `w:real^1`] SEGMENT_TO_POINT_EXISTS) THEN ASM_SIMP_TAC[CLOSED_INTER; CLOSED_INTERVAL] THEN ANTS_TAC THENL [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `x:real^1` THEN ASM_REWRITE_TAC[IN_INTER; IN_INTERVAL_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^1` THEN REWRITE_TAC[IN_INTER] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE `s INTER t INTER u = {} ==> s SUBSET u ==> s INTER t = {}`)) THEN REWRITE_TAC[SEGMENT_1] THEN COND_CASES_TAC THENL [RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_MESON_TAC[DROP_EQ; REAL_LE_ANTISYM]; ANTS_TAC THENL [REWRITE_TAC[SUBSET_INTERVAL_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; REWRITE_TAC[OPEN_CLOSED_INTERVAL_1] THEN ASM SET_TAC[]]]]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u:real^1` THEN STRIP_TAC THEN SUBGOAL_THEN `?v. v IN (s:num->real^1->bool) n /\ v IN interval[z,y] /\ (interval[z,v] DELETE v) INTER (s n) = {}` MP_TAC THENL [ASM_CASES_TAC `z IN (s:num->real^1->bool) n` THENL [EXISTS_TAC `z:real^1` THEN ASM_REWRITE_TAC[ENDS_IN_INTERVAL] THEN REWRITE_TAC[INTERVAL_SING; SET_RULE `{a} DELETE a = {}`] THEN REWRITE_TAC[INTER_EMPTY; INTERVAL_NE_EMPTY_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN MP_TAC(ISPECL [`(s:num->real^1->bool) n INTER interval[z,y]`; `z:real^1`] SEGMENT_TO_POINT_EXISTS) THEN ASM_SIMP_TAC[CLOSED_INTER; CLOSED_INTERVAL] THEN ANTS_TAC THENL [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `y:real^1` THEN ASM_REWRITE_TAC[IN_INTER; IN_INTERVAL_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^1` THEN REWRITE_TAC[IN_INTER] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE `s INTER t INTER u = {} ==> s SUBSET u ==> s INTER t = {}`)) THEN REWRITE_TAC[SEGMENT_1] THEN COND_CASES_TAC THENL [ANTS_TAC THENL [REWRITE_TAC[SUBSET_INTERVAL_1] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; REWRITE_TAC[OPEN_CLOSED_INTERVAL_1] THEN ASM SET_TAC[]]; RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_MESON_TAC[DROP_EQ; REAL_LE_ANTISYM]]]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^1` THEN STRIP_TAC THEN REPEAT CONJ_TAC THENL [ASM SET_TAC[]; ASM SET_TAC[]; RULE_ASSUM_TAC(REWRITE_RULE[NORM_REAL; GSYM drop; DROP_SUB]) THEN REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; RULE_ASSUM_TAC(REWRITE_RULE[NORM_REAL; GSYM drop; DROP_SUB]) THEN REWRITE_TAC[NORM_REAL; GSYM drop; DROP_SUB] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `n:num` THEN ASM_REWRITE_TAC[SEGMENT_1] THEN COND_CASES_TAC THENL [MAP_EVERY UNDISCH_TAC [`interval[w,z] INTER (s:num->real^1->bool) n = {}`; `interval[u,w] DELETE u INTER (s:num->real^1->bool) n = {}`; `interval[z,v] DELETE v INTER (s:num->real^1->bool) n = {}`] THEN REWRITE_TAC[IMP_IMP; SET_RULE `s1 INTER t = {} /\ s2 INTER t = {} <=> (s1 UNION s2) INTER t = {}`] THEN MATCH_MP_TAC(SET_RULE `t SUBSET s ==> s INTER u = {} ==> t INTER u = {}`) THEN REWRITE_TAC[SUBSET; IN_UNION; IN_DELETE; GSYM DROP_EQ; IN_INTERVAL_1] THEN ASM_REAL_ARITH_TAC; RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC]]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `t:real^1->bool` STRIP_ASSUME_TAC) THEN ASM_CASES_TAC `t:real^1->bool = {}` THENL [ASM_MESON_TAC[IN_IMAGE; NOT_IN_EMPTY]; ALL_TAC] THEN ABBREV_TAC `h = \x. (f:real^1->real^N)(@y. y IN t /\ segment(x,y) INTER t = {})` THEN SUBGOAL_THEN `!x y. y IN t /\ segment(x,y) INTER t = {} ==> h(x) = (f:real^1->real^N)(y)` ASSUME_TAC THENL [SUBGOAL_THEN `!x y z. y IN t /\ segment(x,y) INTER t = {} /\ z IN t /\ segment(x,z) INTER t = {} ==> (f:real^1->real^N)(y) = f(z)` ASSUME_TAC THENL [REPEAT GEN_TAC THEN ASM_CASES_TAC `(x:real^1) IN t` THENL [ASM_MESON_TAC[]; UNDISCH_TAC `~((x:real^1) IN t)`] THEN ONCE_REWRITE_TAC[TAUT `p ==> a /\ b /\ c /\ d ==> q <=> (a /\ c) ==> p /\ b /\ d ==> q`] THEN STRIP_TAC THEN REWRITE_TAC[SET_RULE `~(x IN t) /\ s INTER t = {} /\ s' INTER t = {} <=> (x INSERT (s UNION s')) INTER t = {}`] THEN DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(SET_RULE `s SUBSET s' ==> s' INTER t = {} ==> s INTER t = {}`) THEN REWRITE_TAC[SEGMENT_1; SUBSET; IN_UNION; IN_INSERT; IN_INTERVAL_1] THEN GEN_TAC THEN REWRITE_TAC[GSYM DROP_EQ] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; REPEAT STRIP_TAC THEN EXPAND_TAC "h" THEN ASM_MESON_TAC[]]; ALL_TAC] THEN SUBGOAL_THEN `!x. x IN t ==> h(x) = (f:real^1->real^N)(x)` ASSUME_TAC THENL [REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[SEGMENT_REFL; INTER_EMPTY]; ALL_TAC] THEN SUBGOAL_THEN `!x:real^1. ?y. y IN t /\ segment(x,y) INTER t = {}` ASSUME_TAC THENL [X_GEN_TAC `x:real^1` THEN EXISTS_TAC `closest_point t (x:real^1)` THEN ASM_SIMP_TAC[SEGMENT_TO_CLOSEST_POINT; CLOSEST_POINT_EXISTS]; ALL_TAC] THEN SUBGOAL_THEN `!x y. segment(x,y) INTER t = {} ==> (h:real^1->real^N) x = h y` ASSUME_TAC THENL [MAP_EVERY X_GEN_TAC [`x:real^1`; `x':real^1`] THEN ASM_CASES_TAC `(x:real^1) IN t` THENL [ASM_MESON_TAC[SEGMENT_SYM]; ALL_TAC] THEN ASM_CASES_TAC `(x':real^1) IN t` THENL [ASM_MESON_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `?y y'. y IN t /\ segment(x,y) INTER t = {} /\ h x = f y /\ y' IN t /\ segment(x',y') INTER t = {} /\ (h:real^1->real^N) x' = f y'` STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN MAP_EVERY UNDISCH_TAC [`~((x:real^1) IN t)`; `~((x':real^1) IN t)`; `segment(x:real^1,y) INTER t = {}`; `segment(x':real^1,y') INTER t = {}`; `segment(x:real^1,x') INTER t = {}`] THEN MATCH_MP_TAC(SET_RULE `s SUBSET (x1 INSERT x2 INSERT (s0 UNION s1 UNION s2)) ==> s0 INTER t = {} ==> s1 INTER t = {} ==> s2 INTER t = {} ==> ~(x1 IN t) ==> ~(x2 IN t) ==> s INTER t = {}`) THEN REWRITE_TAC[SEGMENT_1; SUBSET; IN_UNION; IN_INSERT; IN_INTERVAL_1] THEN GEN_TAC THEN REWRITE_TAC[GSYM DROP_EQ] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; ALL_TAC] THEN MP_TAC(ISPEC `h:real^1->real^N` HOMEOMORPHIC_MONOTONE_IMAGE_INTERVAL) THEN ANTS_TAC THENL [REPEAT CONJ_TAC THENL [REWRITE_TAC[continuous_on] THEN X_GEN_TAC `u:real^1` THEN DISCH_TAC THEN X_GEN_TAC `e:real` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [continuous_on]) THEN DISCH_THEN(MP_TAC o SPEC `u:real^1`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(MP_TAC o SPEC `e / &2`) THEN ASM_REWRITE_TAC[REAL_HALF] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `d:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN X_GEN_TAC `v:real^1` THEN STRIP_TAC THEN ASM_CASES_TAC `segment(u:real^1,v) INTER t = {}` THENL [ASM_MESON_TAC[DIST_REFL]; ALL_TAC] THEN SUBGOAL_THEN `(?w:real^1. w IN t /\ w IN segment[u,v] /\ segment(u,w) INTER t = {}) /\ (?z:real^1. z IN t /\ z IN segment[u,v] /\ segment(v,z) INTER t = {})` STRIP_ASSUME_TAC THENL [CONJ_TAC THENL [MP_TAC(ISPECL [`segment[u:real^1,v] INTER t`; `u:real^1`] SEGMENT_TO_POINT_EXISTS); MP_TAC(ISPECL [`segment[u:real^1,v] INTER t`; `v:real^1`] SEGMENT_TO_POINT_EXISTS)] THEN (ASM_SIMP_TAC[CLOSED_INTER; CLOSED_SEGMENT] THEN ANTS_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `~(segment(u,v) INTER t = {}) ==> segment(u,v) SUBSET segment[u,v] ==> ~(segment[u,v] INTER t = {})`)) THEN REWRITE_TAC[SEGMENT_OPEN_SUBSET_CLOSED]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `w:real^1` THEN SIMP_TAC[IN_INTER] THEN MATCH_MP_TAC(SET_RULE `(w IN uv ==> uw SUBSET uv) ==> (w IN uv /\ w IN t) /\ (uw INTER uv INTER t = {}) ==> uw INTER t = {}`) THEN DISCH_TAC THEN REWRITE_TAC[open_segment] THEN MATCH_MP_TAC(SET_RULE `s SUBSET t ==> s DIFF u SUBSET t`) THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[GSYM SEGMENT_CONVEX_HULL; CONVEX_SEGMENT] THEN ASM_REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET; ENDS_IN_SEGMENT]); SUBGOAL_THEN `(h:real^1->real^N) u = (f:real^1->real^N) w /\ (h:real^1->real^N) v = (f:real^1->real^N) z` (fun th -> REWRITE_TAC[th]) THENL [ASM_MESON_TAC[]; ALL_TAC] THEN MATCH_MP_TAC(NORM_ARITH `!u. dist(w:real^N,u) < e / &2 /\ dist(z,u) < e / &2 ==> dist(w,z) < e`) THEN EXISTS_TAC `(f:real^1->real^N) u` THEN CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN (CONJ_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `x IN s ==> s SUBSET t ==> x IN t`)) THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC HULL_MINIMAL THEN ASM_REWRITE_TAC[CONVEX_INTERVAL; INSERT_SUBSET; EMPTY_SUBSET]; ASM_MESON_TAC[DIST_IN_CLOSED_SEGMENT; REAL_LET_TRANS; DIST_SYM]])]; X_GEN_TAC `z:real^N` THEN REWRITE_TAC[CONNECTED_IFF_CONNECTED_COMPONENT] THEN MAP_EVERY X_GEN_TAC [`u:real^1`; `v:real^1`] THEN REWRITE_TAC[IN_ELIM_THM] THEN STRIP_TAC THEN REWRITE_TAC[connected_component] THEN EXISTS_TAC `segment[u:real^1,v]` THEN REWRITE_TAC[CONNECTED_SEGMENT; ENDS_IN_SEGMENT] THEN ASM_CASES_TAC `segment(u:real^1,v) INTER t = {}` THENL [REWRITE_TAC[SET_RULE `s SUBSET {x | x IN t /\ P x} <=> s SUBSET t /\ !x. x IN s ==> P x`] THEN CONJ_TAC THENL [ASM_MESON_TAC[CONVEX_CONTAINS_SEGMENT; CONVEX_INTERVAL]; X_GEN_TAC `x:real^1` THEN DISCH_TAC THEN SUBGOAL_THEN `segment(u:real^1,x) INTER t = {}` (fun th -> ASM_MESON_TAC[th]) THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `uv INTER t = {} ==> ux SUBSET uv ==> ux INTER t = {}`)) THEN UNDISCH_TAC `(x:real^1) IN segment[u,v]` THEN REWRITE_TAC[SEGMENT_1] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1; SUBSET_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC]; ALL_TAC] THEN FIRST_X_ASSUM(MP_TAC o SPEC `t DIFF segment(u:real^1,v)`) THEN ASM_REWRITE_TAC[SET_RULE `t DIFF s PSUBSET t <=> ~(s INTER t = {})`] THEN MATCH_MP_TAC(TAUT `p ==> ~p ==> q`) THEN REPEAT CONJ_TAC THENL [ASM SET_TAC[]; MATCH_MP_TAC CLOSED_DIFF THEN ASM_REWRITE_TAC[OPEN_SEGMENT_1]; ASM SET_TAC[]; ASM_REWRITE_TAC[IN_DIFF] THEN MAP_EVERY UNDISCH_TAC [`(u:real^1) IN interval[vec 0,vec 1]`; `(v:real^1) IN interval[vec 0,vec 1]`] THEN REWRITE_TAC[SEGMENT_1] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; ASM_REWRITE_TAC[IN_DIFF] THEN MAP_EVERY UNDISCH_TAC [`(u:real^1) IN interval[vec 0,vec 1]`; `(v:real^1) IN interval[vec 0,vec 1]`] THEN REWRITE_TAC[SEGMENT_1] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC; MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN REWRITE_TAC[IN_DIFF] THEN STRIP_TAC THEN ASM_CASES_TAC `segment(x:real^1,y) INTER segment(u,v) = {}` THENL [ASM SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `(segment(x:real^1,u) SUBSET segment(x,y) DIFF segment(u,v) /\ segment(y:real^1,v) SUBSET segment(x,y) DIFF segment(u,v)) \/ (segment(y:real^1,u) SUBSET segment(x,y) DIFF segment(u,v) /\ segment(x:real^1,v) SUBSET segment(x,y) DIFF segment(u,v))` MP_TAC THENL [MAP_EVERY UNDISCH_TAC [`~(x IN segment(u:real^1,v))`; `~(y IN segment(u:real^1,v))`; `~(segment(x:real^1,y) INTER segment (u,v) = {})`] THEN POP_ASSUM_LIST(K ALL_TAC) THEN MAP_EVERY (fun t -> SPEC_TAC(t,t)) [`v:real^1`; `u:real^1`; `y:real^1`; `x:real^1`] THEN REWRITE_TAC[FORALL_LIFT] THEN MATCH_MP_TAC REAL_WLOG_LE THEN CONJ_TAC THENL [REWRITE_TAC[SEGMENT_SYM] THEN MESON_TAC[]; ALL_TAC] THEN REWRITE_TAC[FORALL_DROP; LIFT_DROP] THEN MAP_EVERY X_GEN_TAC [`x:real^1`; `y:real^1`] THEN DISCH_TAC THEN REWRITE_TAC[FORALL_LIFT] THEN MATCH_MP_TAC REAL_WLOG_LE THEN CONJ_TAC THENL [REWRITE_TAC[SEGMENT_SYM] THEN MESON_TAC[]; ALL_TAC] THEN REWRITE_TAC[FORALL_DROP; LIFT_DROP] THEN MAP_EVERY X_GEN_TAC [`u:real^1`; `v:real^1`] THEN DISCH_TAC THEN ASM_REWRITE_TAC[SEGMENT_1] THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN REWRITE_TAC[IN_INTERVAL_1; SUBSET; IN_DIFF; AND_FORALL_THM] THEN ASM_REAL_ARITH_TAC; DISCH_THEN(DISJ_CASES_THEN(CONJUNCTS_THEN (let sl = SET_RULE `i SUBSET xy DIFF uv ==> xy INTER (t DIFF uv) = {} ==> i INTER t = {}` in fun th -> FIRST_ASSUM(MP_TAC o MATCH_MP (MATCH_MP sl th))))) THEN ASM_MESON_TAC[]]]; ASM_MESON_TAC[]]; DISCH_TAC] THEN SUBGOAL_THEN `?q:real^1->real^N. arc q /\ path_image q SUBSET path_image f /\ a IN path_image q /\ b IN path_image q` STRIP_ASSUME_TAC THENL [FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [homeomorphic]) THEN REWRITE_TAC[homeomorphism] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `q:real^1->real^N` THEN REWRITE_TAC[arc; path; path_image] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THENL [ASM MESON_TAC[]; REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; path_image] THEN ASM SET_TAC[]; REWRITE_TAC[IN_IMAGE] THEN EXISTS_TAC `vec 0:real^1` THEN REWRITE_TAC[ENDS_IN_UNIT_INTERVAL] THEN ASM_MESON_TAC[]; REWRITE_TAC[IN_IMAGE] THEN EXISTS_TAC `vec 1:real^1` THEN REWRITE_TAC[ENDS_IN_UNIT_INTERVAL] THEN ASM_MESON_TAC[]]; SUBGOAL_THEN `?u v. u IN interval[vec 0,vec 1] /\ a = (q:real^1->real^N) u /\ v IN interval[vec 0,vec 1] /\ b = (q:real^1->real^N) v` STRIP_ASSUME_TAC THENL [RULE_ASSUM_TAC(REWRITE_RULE[path_image]) THEN ASM SET_TAC[]; ALL_TAC] THEN EXISTS_TAC `subpath u v (q:real^1->real^N)` THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC ARC_SIMPLE_PATH_SUBPATH THEN ASM_MESON_TAC[ARC_IMP_SIMPLE_PATH]; ASM_MESON_TAC[SUBSET_TRANS; PATH_IMAGE_SUBPATH_SUBSET; ARC_IMP_PATH]; ASM_MESON_TAC[pathstart; PATHSTART_SUBPATH]; ASM_MESON_TAC[pathfinish; PATHFINISH_SUBPATH]]]);;
let PATH_CONNECTED_ARCWISE = 
prove (`!s:real^N->bool. path_connected s <=> !x y. x IN s /\ y IN s /\ ~(x = y) ==> ?g. arc g /\ path_image g SUBSET s /\ pathstart g = x /\ pathfinish g = y`,
GEN_TAC THEN REWRITE_TAC[path_connected] THEN EQ_TAC THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`x:real^N`; `y:real^N`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`x:real^N`; `y:real^N`]) THEN ASM_REWRITE_TAC[] THENL [DISCH_THEN(X_CHOOSE_THEN `g:real^1->real^N` STRIP_ASSUME_TAC) THEN MP_TAC(ISPECL [`g:real^1->real^N`; `x:real^N`; `y:real^N`] PATH_CONTAINS_ARC) THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN ASM_MESON_TAC[SUBSET_TRANS]; ASM_CASES_TAC `y:real^N = x` THEN ASM_REWRITE_TAC[] THENL [EXISTS_TAC `linepath(y:real^N,y)` THEN ASM_REWRITE_TAC[PATH_LINEPATH; PATHSTART_LINEPATH; PATHFINISH_LINEPATH; PATH_IMAGE_LINEPATH; SEGMENT_REFL; SING_SUBSET]; MATCH_MP_TAC MONO_EXISTS THEN SIMP_TAC[ARC_IMP_PATH]]]);;
let ARC_CONNECTED_TRANS = 
prove (`!g h:real^1->real^N. arc g /\ arc h /\ pathfinish g = pathstart h /\ ~(pathstart g = pathfinish h) ==> ?i. arc i /\ path_image i SUBSET (path_image g UNION path_image h) /\ pathstart i = pathstart g /\ pathfinish i = pathfinish h`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`g ++ h:real^1->real^N`; `pathstart(g):real^N`; `pathfinish(h):real^N`] PATH_CONTAINS_ARC) THEN ASM_SIMP_TAC[PATHSTART_JOIN; PATHFINISH_JOIN; PATH_JOIN_EQ; ARC_IMP_PATH; PATH_IMAGE_JOIN]);;
(* ------------------------------------------------------------------------- *) (* Local versions of topological properties in general. *) (* ------------------------------------------------------------------------- *)
let locally = new_definition
 `locally P (s:real^N->bool) <=>
        !w x. open_in (subtopology euclidean s) w /\ x IN w
              ==> ?u v. open_in (subtopology euclidean s) u /\ P v /\
                        x IN u /\ u SUBSET v /\ v SUBSET w`;;
let LOCALLY_MONO = 
prove (`!P Q s. (!t. P t ==> Q t) /\ locally P s ==> locally Q s`,
REWRITE_TAC[locally] THEN MESON_TAC[]);;
let LOCALLY_OPEN_SUBSET = 
prove (`!P s t:real^N->bool. locally P s /\ open_in (subtopology euclidean s) t ==> locally P t`,
REPEAT GEN_TAC THEN REWRITE_TAC[locally] THEN STRIP_TAC THEN MAP_EVERY X_GEN_TAC [`w:real^N->bool`; `x:real^N`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`w:real^N->bool`; `x:real^N`]) THEN ANTS_TAC THENL [ASM_MESON_TAC[OPEN_IN_TRANS]; ALL_TAC] THEN REPEAT(MATCH_MP_TAC MONO_EXISTS THEN GEN_TAC) THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC OPEN_IN_SUBSET_TRANS THEN EXISTS_TAC `s:real^N->bool` THEN ASM_MESON_TAC[open_in; SUBSET]);;
let LOCALLY_DIFF_CLOSED = 
prove (`!P s t:real^N->bool. locally P s /\ closed_in (subtopology euclidean s) t ==> locally P (s DIFF t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC LOCALLY_OPEN_SUBSET THEN EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC OPEN_IN_DIFF THEN ASM_REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_REFL; SUBSET_UNIV; TOPSPACE_EUCLIDEAN]);;
let LOCALLY_EMPTY = 
prove (`!P. locally P {}`,
REWRITE_TAC[locally] THEN MESON_TAC[open_in; SUBSET; NOT_IN_EMPTY]);;
let LOCALLY_SING = 
prove (`!P a. locally P {a} <=> P {a}`,
REWRITE_TAC[locally; open_in] THEN REWRITE_TAC[SET_RULE `(w SUBSET {a} /\ P) /\ x IN w <=> w = {a} /\ x = a /\ P`] THEN SIMP_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2; IN_SING] THEN REWRITE_TAC[SET_RULE `(u SUBSET {a} /\ P) /\ Q /\ a IN u /\ u SUBSET v /\ v SUBSET {a} <=> u = {a} /\ v = {a} /\ P /\ Q`] THEN REWRITE_TAC[RIGHT_EXISTS_AND_THM; UNWIND_THM2; IN_SING] THEN REWRITE_TAC[FORALL_UNWIND_THM2; MESON[REAL_LT_01] `?x. &0 < x`]);;
let LOCALLY_INTER = 
prove (`!P:(real^N->bool)->bool. (!s t. P s /\ P t ==> P(s INTER t)) ==> !s t. locally P s /\ locally P t ==> locally P (s INTER t)`,
GEN_TAC THEN DISCH_TAC THEN REPEAT GEN_TAC THEN REWRITE_TAC[locally; OPEN_IN_OPEN] THEN REWRITE_TAC[LEFT_AND_EXISTS_THM; GSYM CONJ_ASSOC; MESON[] `(!w x. (?t. P t /\ w = f t) /\ Q w x ==> R w x) <=> (!t x. P t /\ Q (f t) x ==> R (f t) x)`] THEN ONCE_REWRITE_TAC[MESON[] `(?a b c. P a b c /\ Q a b c /\ R a b c) <=> (?b c a. Q a b c /\ P a b c /\ R a b c)`] THEN REWRITE_TAC[AND_FORALL_THM; UNWIND_THM2; IN_INTER] THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `w:real^N->bool` THEN MATCH_MP_TAC MONO_FORALL THEN X_GEN_TAC `x:real^N` THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_THEN `u1:real^N->bool` (X_CHOOSE_THEN `v1:real^N->bool` STRIP_ASSUME_TAC)) (X_CHOOSE_THEN `u2:real^N->bool` (X_CHOOSE_THEN `v2:real^N->bool` STRIP_ASSUME_TAC))) THEN EXISTS_TAC `u1 INTER u2:real^N->bool` THEN EXISTS_TAC `v1 INTER v2:real^N->bool` THEN ASM_SIMP_TAC[OPEN_INTER] THEN ASM SET_TAC[]);;
let HOMEOMORPHISM_LOCALLY = 
prove (`!P Q f:real^N->real^M g. (!s t. homeomorphism (s,t) (f,g) ==> (P s <=> Q t)) ==> (!s t. homeomorphism (s,t) (f,g) ==> (locally P s <=> locally Q t))`,
let lemma = prove
   (`!P Q f g.
        (!s t. P s /\ homeomorphism (s,t) (f,g) ==> Q t)
        ==> (!s:real^N->bool t:real^M->bool.
                locally P s /\ homeomorphism (s,t) (f,g) ==> locally Q t)`,
    REPEAT GEN_TAC THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
    REWRITE_TAC[locally] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(STRIP_ASSUME_TAC o GEN_REWRITE_RULE I [homeomorphism]) THEN
    MAP_EVERY X_GEN_TAC [`w:real^M->bool`; `y:real^M`] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(MP_TAC o SPECL
     [`IMAGE (g:real^M->real^N) w`; `(g:real^M->real^N) y`]) THEN
    ANTS_TAC THENL
     [CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
      SUBGOAL_THEN `IMAGE (g:real^M->real^N) w =
                     {x | x IN s /\ f(x) IN w}`
      SUBST1_TAC THENL
       [RULE_ASSUM_TAC(REWRITE_RULE[open_in]) THEN ASM SET_TAC[];
        MATCH_MP_TAC CONTINUOUS_ON_IMP_OPEN_IN THEN ASM_REWRITE_TAC[]];
      REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN
    MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN
    STRIP_TAC THEN MAP_EVERY EXISTS_TAC
     [`IMAGE (f:real^N->real^M) u`; `IMAGE (f:real^N->real^M) v`] THEN
    CONJ_TAC THENL
     [SUBGOAL_THEN `IMAGE (f:real^N->real^M) u =
                     {x | x IN t /\ g(x) IN u}`
      SUBST1_TAC THENL
       [RULE_ASSUM_TAC(REWRITE_RULE[open_in]) THEN ASM SET_TAC[];
        MATCH_MP_TAC CONTINUOUS_ON_IMP_OPEN_IN THEN ASM_REWRITE_TAC[]];
      ALL_TAC] THEN
    CONJ_TAC THENL
     [FIRST_X_ASSUM MATCH_MP_TAC THEN EXISTS_TAC `v:real^N->bool` THEN
      ASM_REWRITE_TAC[homeomorphism] THEN
      REWRITE_TAC[homeomorphism] THEN REPEAT CONJ_TAC THEN
      TRY(FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ]
          CONTINUOUS_ON_SUBSET)));
      ALL_TAC] THEN
    RULE_ASSUM_TAC(REWRITE_RULE[open_in]) THEN ASM SET_TAC[]) in
  REPEAT STRIP_TAC THEN EQ_TAC THEN
  MATCH_MP_TAC(REWRITE_RULE[RIGHT_IMP_FORALL_THM;
        TAUT `p ==> q /\ r ==> s <=> p /\ r ==> q ==> s`] lemma) THEN
  ASM_MESON_TAC[HOMEOMORPHISM_SYM]);;
let HOMEOMORPHIC_LOCALLY = 
prove (`!P Q. (!s:real^N->bool t:real^M->bool. s homeomorphic t ==> (P s <=> Q t)) ==> (!s t. s homeomorphic t ==> (locally P s <=> locally Q t))`,
REPEAT GEN_TAC THEN STRIP_TAC THEN REWRITE_TAC[homeomorphic; LEFT_IMP_EXISTS_THM] THEN ONCE_REWRITE_TAC[MESON[] `(!a b c d. P a b c d) <=> (!c d a b. P a b c d)`] THEN GEN_TAC THEN GEN_TAC THEN MATCH_MP_TAC HOMEOMORPHISM_LOCALLY THEN ASM_MESON_TAC[homeomorphic]);;
let LOCALLY_TRANSLATION = 
prove (`!P:(real^N->bool)->bool. (!a s. P (IMAGE (\x. a + x) s) <=> P s) ==> (!a s. locally P (IMAGE (\x. a + x) s) <=> locally P s)`,
GEN_TAC THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN MP_TAC(ISPECL [`P:(real^N->bool)->bool`; `P:(real^N->bool)->bool`; `\x:real^N. a + x`; `\x:real^N. --a + x`] HOMEOMORPHISM_LOCALLY) THEN REWRITE_TAC[homeomorphism] THEN SIMP_TAC[CONTINUOUS_ON_ADD; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID] THEN REWRITE_TAC[FORALL_UNWIND_THM1; IMP_CONJ; GSYM IMAGE_o; o_DEF; IMAGE_ID; VECTOR_ARITH `--a + a + x:real^N = x /\ a + --a + x = x`] THEN MESON_TAC[]);;
let LOCALLY_INJECTIVE_LINEAR_IMAGE = 
prove (`!P:(real^N->bool)->bool Q:(real^M->bool)->bool. (!f s. linear f /\ (!x y. f x = f y ==> x = y) ==> (P (IMAGE f s) <=> Q s)) ==> (!f s. linear f /\ (!x y. f x = f y ==> x = y) ==> (locally P (IMAGE f s) <=> locally Q s))`,
GEN_TAC THEN GEN_TAC THEN MATCH_MP_TAC MONO_FORALL THEN GEN_TAC THEN ASM_CASES_TAC `linear(f:real^M->real^N) /\ (!x y. f x = f y ==> x = y)` THEN ASM_REWRITE_TAC[] THEN FIRST_ASSUM(MP_TAC o MATCH_MP LINEAR_INJECTIVE_LEFT_INVERSE) THEN REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN DISCH_THEN(X_CHOOSE_THEN `g:real^N->real^M` STRIP_ASSUME_TAC) THEN MP_TAC(ISPECL [`Q:(real^M->bool)->bool`; `P:(real^N->bool)->bool`; `f:real^M->real^N`; `g:real^N->real^M`] HOMEOMORPHISM_LOCALLY) THEN ASM_SIMP_TAC[homeomorphism; LINEAR_CONTINUOUS_ON] THEN ASM_REWRITE_TAC[FORALL_UNWIND_THM1; IMP_CONJ; FORALL_IN_IMAGE] THEN ASM_REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID] THEN MESON_TAC[]);;
let LOCALLY_OPEN_MAP_IMAGE = 
prove (`!P Q f:real^M->real^N s. f continuous_on s /\ (!t. open_in (subtopology euclidean s) t ==> open_in (subtopology euclidean (IMAGE f s)) (IMAGE f t)) /\ (!t. t SUBSET s /\ P t ==> Q(IMAGE f t)) /\ locally P s ==> locally Q (IMAGE f s)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN REWRITE_TAC[locally] THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`w:real^N->bool`; `y:real^N`] THEN STRIP_TAC THEN FIRST_ASSUM(ASSUME_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN FIRST_ASSUM(MP_TAC o SPEC `w:real^N->bool` o GEN_REWRITE_RULE I [CONTINUOUS_ON_OPEN]) THEN ASM_REWRITE_TAC[] THEN DISCH_TAC THEN SUBGOAL_THEN `?x. x IN s /\ (f:real^M->real^N) x = y` STRIP_ASSUME_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN FIRST_X_ASSUM(MP_TAC o SPECL [`{x | x IN s /\ (f:real^M->real^N) x IN w}`; `x:real^M`]) THEN ASM_REWRITE_TAC[IN_ELIM_THM; LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `v:real^M->bool`] THEN STRIP_TAC THEN MAP_EVERY EXISTS_TAC [`IMAGE (f:real^M->real^N) u`; `IMAGE (f:real^M->real^N) v`] THEN ASM_SIMP_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Important special cases of local connectedness & path connectedness. *) (* ------------------------------------------------------------------------- *) let LOCALLY_CONNECTED,LOCALLY_CONNECTED_OPEN_CONNECTED_COMPONENT = (CONJ_PAIR o prove) (`(!s:real^N->bool. locally connected s <=> !v x. open_in (subtopology euclidean s) v /\ x IN v ==> ?u. open_in (subtopology euclidean s) u /\ connected u /\ x IN u /\ u SUBSET v) /\ (!s:real^N->bool. locally connected s <=> !t x. open_in (subtopology euclidean s) t /\ x IN t ==> open_in (subtopology euclidean s) (connected_component t x))`, REWRITE_TAC[AND_FORALL_THM; locally] THEN X_GEN_TAC `s:real^N->bool` THEN MATCH_MP_TAC(TAUT `(q ==> p) /\ (p ==> r) /\ (r ==> q) ==> (p <=> q) /\ (p <=> r)`) THEN REPEAT CONJ_TAC THENL [MESON_TAC[SUBSET_REFL]; DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `y:real^N`] THEN STRIP_TAC THEN ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP CONNECTED_COMPONENT_EQ) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^N->bool`; `x:real^N`]) THEN ANTS_TAC THENL [ASM_MESON_TAC[CONNECTED_COMPONENT_SUBSET; SUBSET]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` (X_CHOOSE_THEN `a:real^N->bool` STRIP_ASSUME_TAC)) THEN EXISTS_TAC `v:real^N->bool` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `a:real^N->bool` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]; DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `x:real^N`] THEN STRIP_TAC THEN EXISTS_TAC `connected_component u (x:real^N)` THEN REWRITE_TAC[CONNECTED_COMPONENT_SUBSET; CONNECTED_CONNECTED_COMPONENT] THEN ASM_SIMP_TAC[IN; CONNECTED_COMPONENT_REFL]]);; let LOCALLY_PATH_CONNECTED,LOCALLY_PATH_CONNECTED_OPEN_PATH_COMPONENT = (CONJ_PAIR o prove) (`(!s:real^N->bool. locally path_connected s <=> !v x. open_in (subtopology euclidean s) v /\ x IN v ==> ?u. open_in (subtopology euclidean s) u /\ path_connected u /\ x IN u /\ u SUBSET v) /\ (!s:real^N->bool. locally path_connected s <=> !t x. open_in (subtopology euclidean s) t /\ x IN t ==> open_in (subtopology euclidean s) (path_component t x))`, REWRITE_TAC[AND_FORALL_THM; locally] THEN X_GEN_TAC `s:real^N->bool` THEN MATCH_MP_TAC(TAUT `(q ==> p) /\ (p ==> r) /\ (r ==> q) ==> (p <=> q) /\ (p <=> r)`) THEN REPEAT CONJ_TAC THENL [MESON_TAC[SUBSET_REFL]; DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `y:real^N`] THEN STRIP_TAC THEN ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP PATH_COMPONENT_EQ) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^N->bool`; `x:real^N`]) THEN ANTS_TAC THENL [ASM_MESON_TAC[PATH_COMPONENT_SUBSET; SUBSET]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` (X_CHOOSE_THEN `a:real^N->bool` STRIP_ASSUME_TAC)) THEN EXISTS_TAC `v:real^N->bool` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `a:real^N->bool` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC PATH_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]; DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `x:real^N`] THEN STRIP_TAC THEN EXISTS_TAC `path_component u (x:real^N)` THEN REWRITE_TAC[PATH_COMPONENT_SUBSET; PATH_CONNECTED_PATH_COMPONENT] THEN ASM_SIMP_TAC[IN; PATH_COMPONENT_REFL]]);;
let LOCALLY_CONNECTED_OPEN_COMPONENT = 
prove (`!s:real^N->bool. locally connected s <=> !t c. open_in (subtopology euclidean s) t /\ c IN components t ==> open_in (subtopology euclidean s) c`,
REWRITE_TAC[LOCALLY_CONNECTED_OPEN_CONNECTED_COMPONENT] THEN REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; components; FORALL_IN_GSPEC]);;
let LOCALLY_CONNECTED_IM_KLEINEN = 
prove (`!s:real^N->bool. locally connected s <=> !v x. open_in (subtopology euclidean s) v /\ x IN v ==> ?u. open_in (subtopology euclidean s) u /\ x IN u /\ u SUBSET v /\ !y. y IN u ==> ?c. connected c /\ c SUBSET v /\ x IN c /\ y IN c`,
GEN_TAC THEN EQ_TAC THENL [REWRITE_TAC[LOCALLY_CONNECTED] THEN MESON_TAC[SUBSET_REFL]; DISCH_TAC] THEN REWRITE_TAC[LOCALLY_CONNECTED_OPEN_COMPONENT] THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `c:real^N->bool`] THEN STRIP_TAC THEN ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^N->bool`; `x:real^N`]) THEN ANTS_TAC THENL [ASM_MESON_TAC[IN_COMPONENTS_SUBSET; SUBSET]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET] THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `k:real^N->bool` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `(k:real^N->bool) SUBSET c` MP_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN MATCH_MP_TAC COMPONENTS_MAXIMAL THEN EXISTS_TAC `u:real^N->bool` THEN ASM SET_TAC[]);;
let LOCALLY_PATH_CONNECTED_IM_KLEINEN = 
prove (`!s:real^N->bool. locally path_connected s <=> !v x. open_in (subtopology euclidean s) v /\ x IN v ==> ?u. open_in (subtopology euclidean s) u /\ x IN u /\ u SUBSET v /\ !y. y IN u ==> ?p. path p /\ path_image p SUBSET v /\ pathstart p = x /\ pathfinish p = y`,
GEN_TAC THEN EQ_TAC THENL [REWRITE_TAC[LOCALLY_PATH_CONNECTED] THEN REWRITE_TAC[path_connected] THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN MATCH_MP_TAC MONO_IMP THEN REWRITE_TAC[] THEN MATCH_MP_TAC MONO_EXISTS THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]; REWRITE_TAC[LOCALLY_PATH_CONNECTED_OPEN_PATH_COMPONENT] THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `z:real^N`] THEN STRIP_TAC THEN ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^N->bool`; `x:real^N`]) THEN ANTS_TAC THENL [ASM_MESON_TAC[PATH_COMPONENT_SUBSET; SUBSET]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[SUBSET] THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `p:real^1->real^N` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `(path_image p) SUBSET path_component u (z:real^N)` MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[PATHFINISH_IN_PATH_IMAGE; SUBSET]] THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP PATH_COMPONENT_EQ) THEN MATCH_MP_TAC PATH_COMPONENT_MAXIMAL THEN ASM_SIMP_TAC[PATH_CONNECTED_PATH_IMAGE] THEN ASM_MESON_TAC[PATHSTART_IN_PATH_IMAGE]]);;
let LOCALLY_PATH_CONNECTED_IMP_LOCALLY_CONNECTED = 
prove (`!s:real^N->bool. locally path_connected s ==> locally connected s`,
let LOCALLY_CONNECTED_COMPONENTS = 
prove (`!s c:real^N->bool. locally connected s /\ c IN components s ==> locally connected c`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] LOCALLY_OPEN_SUBSET)) THEN FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [LOCALLY_CONNECTED_OPEN_COMPONENT]) THEN EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[OPEN_IN_REFL]);;
let LOCALLY_CONNECTED_CONNECTED_COMPONENT = 
prove (`!s x:real^N. locally connected s ==> locally connected (connected_component s x)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `connected_component s (x:real^N) = {}` THEN ASM_REWRITE_TAC[LOCALLY_EMPTY] THEN MATCH_MP_TAC LOCALLY_CONNECTED_COMPONENTS THEN EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[IN_COMPONENTS] THEN ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY]);;
let LOCALLY_PATH_CONNECTED_COMPONENTS = 
prove (`!s c:real^N->bool. locally path_connected s /\ c IN components s ==> locally path_connected c`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] LOCALLY_OPEN_SUBSET)) THEN FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [LOCALLY_CONNECTED_OPEN_COMPONENT] o MATCH_MP LOCALLY_PATH_CONNECTED_IMP_LOCALLY_CONNECTED) THEN EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[OPEN_IN_REFL]);;
let LOCALLY_PATH_CONNECTED_CONNECTED_COMPONENT = 
prove (`!s x:real^N. locally path_connected s ==> locally path_connected (connected_component s x)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `connected_component s (x:real^N) = {}` THEN ASM_REWRITE_TAC[LOCALLY_EMPTY] THEN MATCH_MP_TAC LOCALLY_PATH_CONNECTED_COMPONENTS THEN EXISTS_TAC `s:real^N->bool` THEN ASM_REWRITE_TAC[IN_COMPONENTS] THEN ASM_MESON_TAC[CONNECTED_COMPONENT_EQ_EMPTY]);;
let OPEN_IMP_LOCALLY_PATH_CONNECTED = 
prove (`!s:real^N->bool. open s ==> locally path_connected s`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC LOCALLY_MONO THEN EXISTS_TAC `convex:(real^N->bool)->bool` THEN REWRITE_TAC[CONVEX_IMP_PATH_CONNECTED] THEN ASM_SIMP_TAC[locally; OPEN_IN_OPEN_EQ] THEN ASM_MESON_TAC[OPEN_CONTAINS_BALL; CENTRE_IN_BALL; OPEN_BALL; CONVEX_BALL; SUBSET]);;
let OPEN_IMP_LOCALLY_CONNECTED = 
prove (`!s:real^N->bool. open s ==> locally connected s`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC LOCALLY_MONO THEN EXISTS_TAC `path_connected:(real^N->bool)->bool` THEN ASM_SIMP_TAC[OPEN_IMP_LOCALLY_PATH_CONNECTED; PATH_CONNECTED_IMP_CONNECTED]);;
let LOCALLY_PATH_CONNECTED_UNIV = 
prove (`locally path_connected (:real^N)`,
let LOCALLY_CONNECTED_UNIV = 
prove (`locally connected (:real^N)`,
let OPEN_IN_CONNECTED_COMPONENT_LOCALLY_CONNECTED = 
prove (`!s x:real^N. locally connected s ==> open_in (subtopology euclidean s) (connected_component s x)`,
REWRITE_TAC[LOCALLY_CONNECTED_OPEN_CONNECTED_COMPONENT] THEN REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THENL [FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_REFL; SUBSET_UNIV; TOPSPACE_EUCLIDEAN]; ASM_MESON_TAC[OPEN_IN_EMPTY; CONNECTED_COMPONENT_EQ_EMPTY]]);;
let OPEN_IN_COMPONENTS_LOCALLY_CONNECTED = 
prove (`!s c:real^N->bool. locally connected s /\ c IN components s ==> open_in (subtopology euclidean s) c`,
let OPEN_IN_PATH_COMPONENT_LOCALLY_PATH_CONNECTED = 
prove (`!s x:real^N. locally path_connected s ==> open_in (subtopology euclidean s) (path_component s x)`,
REWRITE_TAC[LOCALLY_PATH_CONNECTED_OPEN_PATH_COMPONENT] THEN REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THENL [FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_REFL; SUBSET_UNIV; TOPSPACE_EUCLIDEAN]; ASM_MESON_TAC[OPEN_IN_EMPTY; PATH_COMPONENT_EQ_EMPTY]]);;
let CLOSED_IN_PATH_COMPONENT_LOCALLY_PATH_CONNECTED = 
prove (`!s x:real^N. locally path_connected s ==> closed_in (subtopology euclidean s) (path_component s x)`,
REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY; PATH_COMPONENT_SUBSET] THEN REPEAT STRIP_TAC THEN SUBGOAL_THEN `s DIFF path_component s (x:real^N) = UNIONS({path_component s y | y | y IN s} DELETE (path_component s x))` SUBST1_TAC THENL [GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [GSYM UNIONS_PATH_COMPONENT] THEN MATCH_MP_TAC(SET_RULE `(!x. x IN s DELETE a ==> DISJOINT a x) ==> UNIONS s DIFF a = UNIONS (s DELETE a)`) THEN REWRITE_TAC[IMP_CONJ; FORALL_IN_GSPEC; IN_DELETE] THEN SIMP_TAC[PATH_COMPONENT_DISJOINT; PATH_COMPONENT_EQ_EQ] THEN MESON_TAC[IN; SUBSET; PATH_COMPONENT_SUBSET]; MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[IMP_CONJ; FORALL_IN_GSPEC; IN_DELETE] THEN ASM_SIMP_TAC[OPEN_IN_PATH_COMPONENT_LOCALLY_PATH_CONNECTED]]);;
let CONVEX_IMP_LOCALLY_PATH_CONNECTED = 
prove (`!s:real^N->bool. convex s ==> locally path_connected s`,
REPEAT STRIP_TAC THEN REWRITE_TAC[LOCALLY_PATH_CONNECTED] THEN MAP_EVERY X_GEN_TAC [`v:real^N->bool`; `x:real^N`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM SUBST_ALL_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTER]) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_BALL]) THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `s INTER ball(x:real^N,e)` THEN REPEAT CONJ_TAC THENL [REWRITE_TAC[OPEN_IN_OPEN] THEN MESON_TAC[OPEN_BALL]; MATCH_MP_TAC CONVEX_IMP_PATH_CONNECTED THEN ASM_SIMP_TAC[CONVEX_INTER; CONVEX_BALL]; ASM_REWRITE_TAC[IN_INTER; CENTRE_IN_BALL]; ASM SET_TAC[]]);;
let OPEN_IN_CONNECTED_COMPONENTS = 
prove (`!s c:real^N->bool. FINITE(components s) /\ c IN components s ==> open_in (subtopology euclidean s) c`,
let FINITE_COMPONENTS = 
prove (`!s:real^N->bool. compact s /\ locally connected s ==> FINITE(components s)`,
REPEAT STRIP_TAC THEN FIRST_ASSUM (MP_TAC o GEN_REWRITE_RULE I [COMPACT_EQ_HEINE_BOREL_SUBTOPOLOGY]) THEN DISCH_THEN(MP_TAC o SPEC `components(s:real^N->bool)`) THEN REWRITE_TAC[GSYM UNIONS_COMPONENTS; SUBSET_REFL] THEN ANTS_TAC THENL [ASM_MESON_TAC[OPEN_IN_COMPONENTS_LOCALLY_CONNECTED]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `f:(real^N->bool)->bool` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `components(s:real^N->bool) = f` (fun th -> ASM_REWRITE_TAC[th]) THEN ASM_CASES_TAC `?c:real^N->bool. c IN components s /\ ~(c IN f)` THENL [FIRST_X_ASSUM(CHOOSE_THEN STRIP_ASSUME_TAC); ASM SET_TAC[]] THEN SUBGOAL_THEN `~(c:real^N->bool = {}) /\ c SUBSET UNIONS f /\ DISJOINT c (UNIONS f)` MP_TAC THENL [ALL_TAC; SET_TAC[]] THEN REPEAT CONJ_TAC THENL [ASM_MESON_TAC[IN_COMPONENTS_NONEMPTY]; ASM_MESON_TAC[IN_COMPONENTS_SUBSET; SUBSET_TRANS]; REWRITE_TAC[DISJOINT; INTER_UNIONS; EMPTY_UNIONS; FORALL_IN_GSPEC] THEN REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM DISJOINT] THEN MATCH_MP_TAC(REWRITE_RULE[pairwise] PAIRWISE_DISJOINT_COMPONENTS) THEN ASM_MESON_TAC[SUBSET]]);;
let CONVEX_IMP_LOCALLY_CONNECTED = 
prove (`!s:real^N->bool. convex s ==> locally connected s`,
let HOMEOMORPHIC_LOCAL_CONNECTEDNESS = 
prove (`!s t. s homeomorphic t ==> (locally connected s <=> locally connected t)`,
MATCH_MP_TAC HOMEOMORPHIC_LOCALLY THEN REWRITE_TAC[HOMEOMORPHIC_CONNECTEDNESS]);;
let HOMEOMORPHIC_LOCAL_PATH_CONNECTEDNESS = 
prove (`!s t. s homeomorphic t ==> (locally path_connected s <=> locally path_connected t)`,
MATCH_MP_TAC HOMEOMORPHIC_LOCALLY THEN REWRITE_TAC[HOMEOMORPHIC_PATH_CONNECTEDNESS]);;
let LOCALLY_PATH_CONNECTED_TRANSLATION_EQ = 
prove (`!a:real^N s. locally path_connected (IMAGE (\x. a + x) s) <=> locally path_connected s`,
MATCH_MP_TAC LOCALLY_TRANSLATION THEN REWRITE_TAC[PATH_CONNECTED_TRANSLATION_EQ]);;
add_translation_invariants [LOCALLY_PATH_CONNECTED_TRANSLATION_EQ];;
let LOCALLY_CONNECTED_TRANSLATION_EQ = 
prove (`!a:real^N s. locally connected (IMAGE (\x. a + x) s) <=> locally connected s`,
MATCH_MP_TAC LOCALLY_TRANSLATION THEN REWRITE_TAC[CONNECTED_TRANSLATION_EQ]);;
add_translation_invariants [LOCALLY_CONNECTED_TRANSLATION_EQ];;
let LOCALLY_PATH_CONNECTED_LINEAR_IMAGE_EQ = 
prove (`!f:real^M->real^N s. linear f /\ (!x y. f x = f y ==> x = y) ==> (locally path_connected (IMAGE f s) <=> locally path_connected s)`,
add_linear_invariants [LOCALLY_PATH_CONNECTED_LINEAR_IMAGE_EQ];;
let LOCALLY_CONNECTED_LINEAR_IMAGE_EQ = 
prove (`!f:real^M->real^N s. linear f /\ (!x y. f x = f y ==> x = y) ==> (locally connected (IMAGE f s) <=> locally connected s)`,
add_linear_invariants [LOCALLY_CONNECTED_LINEAR_IMAGE_EQ];;
let LOCALLY_CONNECTED_QUOTIENT_IMAGE = 
prove (`!f:real^M->real^N s. (!t. t SUBSET IMAGE f s ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN t} <=> open_in (subtopology euclidean (IMAGE f s)) t)) /\ locally connected s ==> locally connected (IMAGE f s)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[LOCALLY_CONNECTED_OPEN_COMPONENT] THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `c:real^N->bool`] THEN STRIP_TAC THEN FIRST_ASSUM(ASSUME_TAC o MATCH_MP IN_COMPONENTS_SUBSET) THEN FIRST_ASSUM(ASSUME_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN FIRST_ASSUM(MP_TAC o SPEC `c:real^N->bool`) THEN ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)] THEN ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN X_GEN_TAC `x:real^M` THEN REWRITE_TAC[IN_ELIM_THM] THEN STRIP_TAC THEN EXISTS_TAC `connected_component {w | w IN s /\ (f:real^M->real^N)(w) IN u} x` THEN REPEAT CONJ_TAC THENL [FIRST_X_ASSUM(MP_TAC o SPEC `u:real^N->bool`) THEN ANTS_TAC THENL [ASM SET_TAC[]; ASM_REWRITE_TAC[]] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LOCALLY_CONNECTED_OPEN_COMPONENT]) THEN REWRITE_TAC[IMP_CONJ_ALT] THEN DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[IN_COMPONENTS; IN_ELIM_THM] THEN ASM SET_TAC[]; ALL_TAC; ASSUME_TAC(ISPECL [`{w | w IN s /\ (f:real^M->real^N) w IN u}`; `x:real^M`] CONNECTED_COMPONENT_SUBSET) THEN SUBGOAL_THEN `IMAGE (f:real^M->real^N) (connected_component {w | w IN s /\ f w IN u} x) SUBSET c` MP_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN MATCH_MP_TAC COMPONENTS_MAXIMAL THEN EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN REWRITE_TAC[CONNECTED_CONNECTED_COMPONENT] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:real^M->bool` THEN CONJ_TAC THENL [REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN ASM_MESON_TAC[open_in]; ASM SET_TAC[]]; ASM SET_TAC[]; REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER] THEN EXISTS_TAC `(f:real^M->real^N) x` THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC FUN_IN_IMAGE]] THEN GEN_REWRITE_TAC I [IN] THEN REWRITE_TAC[CONNECTED_COMPONENT_REFL_EQ] THEN ASM SET_TAC[]);;
let LOCALLY_PATH_CONNECTED_QUOTIENT_IMAGE = 
prove (`!f:real^M->real^N s. (!t. t SUBSET IMAGE f s ==> (open_in (subtopology euclidean s) {x | x IN s /\ f x IN t} <=> open_in (subtopology euclidean (IMAGE f s)) t)) /\ locally path_connected s ==> locally path_connected (IMAGE f s)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[LOCALLY_PATH_CONNECTED_OPEN_PATH_COMPONENT] THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `y:real^N`] THEN STRIP_TAC THEN ASSUME_TAC(ISPECL [`u:real^N->bool`; `y:real^N`] PATH_COMPONENT_SUBSET) THEN FIRST_ASSUM(ASSUME_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [open_in]) THEN FIRST_ASSUM(MP_TAC o SPEC `path_component u (y:real^N)`) THEN ANTS_TAC THENL [ASM SET_TAC[]; DISCH_THEN(SUBST1_TAC o SYM)] THEN ONCE_REWRITE_TAC[OPEN_IN_SUBOPEN] THEN X_GEN_TAC `x:real^M` THEN REWRITE_TAC[IN_ELIM_THM] THEN STRIP_TAC THEN EXISTS_TAC `path_component {w | w IN s /\ (f:real^M->real^N)(w) IN u} x` THEN REPEAT CONJ_TAC THENL [FIRST_X_ASSUM(MP_TAC o SPEC `u:real^N->bool`) THEN ANTS_TAC THENL [ASM SET_TAC[]; ASM_REWRITE_TAC[]] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LOCALLY_PATH_CONNECTED_OPEN_PATH_COMPONENT]) THEN REWRITE_TAC[IMP_CONJ_ALT] THEN DISCH_THEN MATCH_MP_TAC THEN ASM SET_TAC[]; ALL_TAC; ASSUME_TAC(ISPECL [`{w | w IN s /\ (f:real^M->real^N) w IN u}`; `x:real^M`] PATH_COMPONENT_SUBSET) THEN SUBGOAL_THEN `IMAGE (f:real^M->real^N) (path_component {w | w IN s /\ f w IN u} x) SUBSET path_component u y` MP_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN FIRST_ASSUM(SUBST1_TAC o SYM o MATCH_MP PATH_COMPONENT_EQ) THEN MATCH_MP_TAC PATH_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC FUN_IN_IMAGE; MATCH_MP_TAC PATH_CONNECTED_CONTINUOUS_IMAGE THEN REWRITE_TAC[PATH_CONNECTED_PATH_COMPONENT] THEN MATCH_MP_TAC CONTINUOUS_ON_SUBSET THEN EXISTS_TAC `s:real^M->bool` THEN CONJ_TAC THENL [REWRITE_TAC[CONTINUOUS_ON_OPEN] THEN ASM_MESON_TAC[open_in]; ASM SET_TAC[]]; ASM SET_TAC[]]] THEN GEN_REWRITE_TAC I [IN] THEN REWRITE_TAC[PATH_COMPONENT_REFL_EQ] THEN ASM SET_TAC[]);;
let LOCALLY_CONNECTED_CONTINUOUS_IMAGE_COMPACT = 
prove (`!f:real^M->real^N s. locally connected s /\ compact s /\ f continuous_on s ==> locally connected (IMAGE f s)`,
let LOCALLY_PATH_CONNECTED_CONTINUOUS_IMAGE_COMPACT = 
prove (`!f:real^M->real^N s. locally path_connected s /\ compact s /\ f continuous_on s ==> locally path_connected (IMAGE f s)`,
let LOCALLY_PATH_CONNECTED_PATH_IMAGE = 
prove (`!p:real^1->real^N. path p ==> locally path_connected (path_image p)`,
REWRITE_TAC[path; path_image] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC LOCALLY_PATH_CONNECTED_CONTINUOUS_IMAGE_COMPACT THEN ASM_SIMP_TAC[COMPACT_INTERVAL; CONVEX_INTERVAL; CONVEX_IMP_LOCALLY_PATH_CONNECTED]);;
let LOCALLY_CONNECTED_PATH_IMAGE = 
prove (`!p:real^1->real^N. path p ==> locally connected (path_image p)`,
let LOCALLY_CONNECTED_LEFT_INVERTIBLE_IMAGE = 
prove (`!f:real^M->real^N g s. f continuous_on s /\ g continuous_on (IMAGE f s) /\ (!x. x IN s ==> g(f x) = x) /\ locally connected s ==> locally connected (IMAGE f s)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LOCALLY_CONNECTED_QUOTIENT_IMAGE) THEN MATCH_MP_TAC CONTINUOUS_LEFT_INVERSE_IMP_QUOTIENT_MAP THEN ASM_MESON_TAC[]);;
let LOCALLY_CONNECTED_RIGHT_INVERTIBLE_IMAGE = 
prove (`!f:real^M->real^N g s. f continuous_on s /\ g continuous_on (IMAGE f s) /\ IMAGE g (IMAGE f s) SUBSET s /\ (!x. x IN IMAGE f s ==> f(g x) = x) /\ locally connected s ==> locally connected (IMAGE f s)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LOCALLY_CONNECTED_QUOTIENT_IMAGE) THEN MATCH_MP_TAC CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP THEN EXISTS_TAC `g:real^N->real^M` THEN ASM SET_TAC[]);;
let LOCALLY_PATH_CONNECTED_LEFT_INVERTIBLE_IMAGE = 
prove (`!f:real^M->real^N g s. f continuous_on s /\ g continuous_on (IMAGE f s) /\ (!x. x IN s ==> g(f x) = x) /\ locally path_connected s ==> locally path_connected (IMAGE f s)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LOCALLY_PATH_CONNECTED_QUOTIENT_IMAGE) THEN MATCH_MP_TAC CONTINUOUS_LEFT_INVERSE_IMP_QUOTIENT_MAP THEN ASM_MESON_TAC[]);;
let LOCALLY_PATH_CONNECTED_RIGHT_INVERTIBLE_IMAGE = 
prove (`!f:real^M->real^N g s. f continuous_on s /\ g continuous_on (IMAGE f s) /\ IMAGE g (IMAGE f s) SUBSET s /\ (!x. x IN IMAGE f s ==> f(g x) = x) /\ locally path_connected s ==> locally path_connected (IMAGE f s)`,
REPEAT GEN_TAC THEN REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] LOCALLY_PATH_CONNECTED_QUOTIENT_IMAGE) THEN MATCH_MP_TAC CONTINUOUS_RIGHT_INVERSE_IMP_QUOTIENT_MAP THEN EXISTS_TAC `g:real^N->real^M` THEN ASM SET_TAC[]);;
let LOCALLY_PCROSS = 
prove (`!P Q R. (!s:real^M->bool t:real^N->bool. P s /\ Q t ==> R(s PCROSS t)) ==> (!s t. locally P s /\ locally Q t ==> locally R (s PCROSS t))`,
REPEAT STRIP_TAC THEN REWRITE_TAC[locally; FORALL_PASTECART] THEN MAP_EVERY X_GEN_TAC [`w:real^(M,N)finite_sum->bool`; `x:real^M`; `y:real^N`] THEN DISCH_THEN(fun th -> STRIP_ASSUME_TAC th THEN MP_TAC(MATCH_MP PASTECART_IN_INTERIOR_SUBTOPOLOGY (ONCE_REWRITE_RULE[CONJ_SYM] th))) THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`u:real^M->bool`; `x:real^M`] o GEN_REWRITE_RULE I [locally]) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`v:real^N->bool`; `y:real^N`] o GEN_REWRITE_RULE I [locally]) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`v':real^N->bool`; `v'':real^N->bool`] THEN STRIP_TAC THEN MAP_EVERY X_GEN_TAC [`u':real^M->bool`; `u'':real^M->bool`] THEN STRIP_TAC THEN EXISTS_TAC `(u':real^M->bool) PCROSS (v':real^N->bool)` THEN EXISTS_TAC `(u'':real^M->bool) PCROSS (v'':real^N->bool)` THEN ASM_SIMP_TAC[PASTECART_IN_PCROSS; PCROSS_MONO; OPEN_IN_PCROSS] THEN ASM_MESON_TAC[PCROSS_MONO; SUBSET_TRANS]);;
let LOCALLY_CONNECTED_PCROSS = 
prove (`!s:real^M->bool t:real^N->bool. locally connected s /\ locally connected t ==> locally connected (s PCROSS t)`,
MATCH_MP_TAC LOCALLY_PCROSS THEN REWRITE_TAC[CONNECTED_PCROSS]);;
let LOCALLY_PATH_CONNECTED_PCROSS = 
prove (`!s:real^M->bool t:real^N->bool. locally path_connected s /\ locally path_connected t ==> locally path_connected (s PCROSS t)`,
MATCH_MP_TAC LOCALLY_PCROSS THEN REWRITE_TAC[PATH_CONNECTED_PCROSS]);;
let LOCALLY_CONNECTED_PCROSS_EQ = 
prove (`!s:real^M->bool t:real^N->bool. locally connected (s PCROSS t) <=> s = {} \/ t = {} \/ locally connected s /\ locally connected t`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[PCROSS_EMPTY; LOCALLY_EMPTY] THEN ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[PCROSS_EMPTY; LOCALLY_EMPTY] THEN EQ_TAC THEN REWRITE_TAC[LOCALLY_CONNECTED_PCROSS] THEN GEN_REWRITE_TAC LAND_CONV [LOCALLY_CONNECTED] THEN DISCH_TAC THEN REWRITE_TAC[LOCALLY_CONNECTED_IM_KLEINEN] THEN CONJ_TAC THENL [MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `x:real^M`] THEN STRIP_TAC THEN UNDISCH_TAC `~(t:real^N->bool = {})` THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN DISCH_THEN(X_CHOOSE_TAC `y:real^N`) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`(u:real^M->bool) PCROSS (t:real^N->bool)`; `pastecart (x:real^M) (y:real^N)`]); MAP_EVERY X_GEN_TAC [`v:real^N->bool`; `y:real^N`] THEN STRIP_TAC THEN UNDISCH_TAC `~(s:real^M->bool = {})` THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN DISCH_THEN(X_CHOOSE_TAC `x:real^M`) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`(s:real^M->bool) PCROSS (v:real^N->bool)`; `pastecart (x:real^M) (y:real^N)`])] THEN ASM_SIMP_TAC[OPEN_IN_PCROSS_EQ; PASTECART_IN_PCROSS; SUBSET_UNIV; OPEN_IN_SUBTOPOLOGY_REFL; TOPSPACE_EUCLIDEAN; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `w:real^(M,N)finite_sum->bool` THEN STRIP_TAC THEN MP_TAC(ISPECL [`s:real^M->bool`; `t:real^N->bool`; `w:real^(M,N)finite_sum->bool`; `x:real^M`; `y:real^N`] PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN ASM_REWRITE_TAC[] THENL [MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u':real^M->bool` THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC) THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; X_GEN_TAC `z:real^M` THEN DISCH_TAC THEN EXISTS_TAC `IMAGE fstcart (w:real^(M,N)finite_sum->bool)` THEN ASM_SIMP_TAC[CONNECTED_LINEAR_IMAGE; LINEAR_FSTCART] THEN REWRITE_TAC[SUBSET; IN_IMAGE; EXISTS_PASTECART; FSTCART_PASTECART]]; DISCH_THEN(X_CHOOSE_THEN `u:real^M->bool` MP_TAC) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v':real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN EXISTS_TAC `IMAGE sndcart (w:real^(M,N)finite_sum->bool)` THEN ASM_SIMP_TAC[CONNECTED_LINEAR_IMAGE; LINEAR_SNDCART] THEN REWRITE_TAC[SUBSET; IN_IMAGE; EXISTS_PASTECART; SNDCART_PASTECART]]] THEN RULE_ASSUM_TAC(REWRITE_RULE [SUBSET; FORALL_IN_PCROSS; PASTECART_IN_PCROSS; FORALL_PASTECART]) THEN ASM SET_TAC[]);;
let LOCALLY_PATH_CONNECTED_PCROSS_EQ = 
prove (`!s:real^M->bool t:real^N->bool. locally path_connected (s PCROSS t) <=> s = {} \/ t = {} \/ locally path_connected s /\ locally path_connected t`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^M->bool = {}` THEN ASM_REWRITE_TAC[PCROSS_EMPTY; LOCALLY_EMPTY] THEN ASM_CASES_TAC `t:real^N->bool = {}` THEN ASM_REWRITE_TAC[PCROSS_EMPTY; LOCALLY_EMPTY] THEN EQ_TAC THEN REWRITE_TAC[LOCALLY_PATH_CONNECTED_PCROSS] THEN GEN_REWRITE_TAC LAND_CONV [LOCALLY_PATH_CONNECTED] THEN DISCH_TAC THEN REWRITE_TAC[LOCALLY_PATH_CONNECTED_IM_KLEINEN] THEN CONJ_TAC THENL [MAP_EVERY X_GEN_TAC [`u:real^M->bool`; `x:real^M`] THEN STRIP_TAC THEN UNDISCH_TAC `~(t:real^N->bool = {})` THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN DISCH_THEN(X_CHOOSE_TAC `y:real^N`) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`(u:real^M->bool) PCROSS (t:real^N->bool)`; `pastecart (x:real^M) (y:real^N)`]); MAP_EVERY X_GEN_TAC [`v:real^N->bool`; `y:real^N`] THEN STRIP_TAC THEN UNDISCH_TAC `~(s:real^M->bool = {})` THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN DISCH_THEN(X_CHOOSE_TAC `x:real^M`) THEN FIRST_X_ASSUM(MP_TAC o SPECL [`(s:real^M->bool) PCROSS (v:real^N->bool)`; `pastecart (x:real^M) (y:real^N)`])] THEN ASM_SIMP_TAC[OPEN_IN_PCROSS_EQ; PASTECART_IN_PCROSS; SUBSET_UNIV; OPEN_IN_SUBTOPOLOGY_REFL; TOPSPACE_EUCLIDEAN; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `w:real^(M,N)finite_sum->bool` THEN STRIP_TAC THEN MP_TAC(ISPECL [`s:real^M->bool`; `t:real^N->bool`; `w:real^(M,N)finite_sum->bool`; `x:real^M`; `y:real^N`] PASTECART_IN_INTERIOR_SUBTOPOLOGY) THEN ASM_REWRITE_TAC[] THENL [MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `u':real^M->bool` THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC) THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; X_GEN_TAC `z:real^M` THEN DISCH_TAC THEN MP_TAC(ISPECL [`fstcart:real^(M,N)finite_sum->real^M`; `w:real^(M,N)finite_sum->bool`] PATH_CONNECTED_LINEAR_IMAGE) THEN ASM_REWRITE_TAC[LINEAR_FSTCART] THEN REWRITE_TAC[path_connected] THEN DISCH_THEN(MP_TAC o SPECL [`x:real^M`; `z:real^M`]) THEN ANTS_TAC THENL [REWRITE_TAC[IN_IMAGE; EXISTS_PASTECART; FSTCART_PASTECART]; MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[SUBSET; IN_IMAGE; EXISTS_PASTECART; FSTCART_PASTECART] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[]]]; DISCH_THEN(X_CHOOSE_THEN `u:real^M->bool` MP_TAC) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `v':real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; X_GEN_TAC `z:real^N` THEN DISCH_TAC THEN MP_TAC(ISPECL [`sndcart:real^(M,N)finite_sum->real^N`; `w:real^(M,N)finite_sum->bool`] PATH_CONNECTED_LINEAR_IMAGE) THEN ASM_REWRITE_TAC[LINEAR_SNDCART] THEN REWRITE_TAC[path_connected] THEN DISCH_THEN(MP_TAC o SPECL [`y:real^N`; `z:real^N`]) THEN ANTS_TAC THENL [REWRITE_TAC[IN_IMAGE; EXISTS_PASTECART; SNDCART_PASTECART]; MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[SUBSET; IN_IMAGE; EXISTS_PASTECART; SNDCART_PASTECART] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[]]]] THEN RULE_ASSUM_TAC(REWRITE_RULE [SUBSET; FORALL_IN_PCROSS; PASTECART_IN_PCROSS; FORALL_PASTECART]) THEN ASM SET_TAC[]);;
let CARD_EQ_OPEN_IN = 
prove (`!u s:real^N->bool. locally connected u /\ open_in (subtopology euclidean u) s /\ (?x. x IN s /\ x limit_point_of u) ==> s =_c (:real)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM CARD_LE_ANTISYM] THEN CONJ_TAC THENL [TRANS_TAC CARD_LE_TRANS `(:real^N)` THEN SIMP_TAC[CARD_EQ_IMP_LE; CARD_EQ_EUCLIDEAN] THEN MATCH_MP_TAC CARD_LE_SUBSET THEN REWRITE_TAC[SUBSET_UNIV]; ALL_TAC] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_OPEN]) THEN DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN UNDISCH_TAC `(x:real^N) IN s` THEN ASM_REWRITE_TAC[IN_INTER] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LOCALLY_CONNECTED]) THEN DISCH_THEN(MP_TAC o SPECL [`u INTER t:real^N->bool`; `x:real^N`]) THEN ASM_SIMP_TAC[OPEN_IN_OPEN_INTER; IN_INTER] THEN REWRITE_TAC[OPEN_IN_OPEN; GSYM CONJ_ASSOC; LEFT_AND_EXISTS_THM] THEN ONCE_REWRITE_TAC[SWAP_EXISTS_THM] THEN ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN REWRITE_TAC[UNWIND_THM2; IN_INTER] THEN DISCH_THEN(X_CHOOSE_THEN `v:real^N->bool` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [limit_point_of]) THEN DISCH_THEN(MP_TAC o SPEC `t INTER v:real^N->bool`) THEN ASM_SIMP_TAC[IN_INTER; OPEN_INTER] THEN DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN TRANS_TAC CARD_LE_TRANS `u INTER v:real^N->bool` THEN ASM_SIMP_TAC[CARD_LE_SUBSET] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN MATCH_MP_TAC CARD_EQ_CONNECTED THEN ASM SET_TAC[]);;
let CARD_EQ_OPEN_IN_AFFINE = 
prove (`!u s:real^N->bool. affine u /\ ~(aff_dim u = &0) /\ open_in (subtopology euclidean u) s /\ ~(s = {}) ==> s =_c (:real)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC CARD_EQ_OPEN_IN THEN EXISTS_TAC `u:real^N->bool` THEN ASM_SIMP_TAC[CONVEX_IMP_LOCALLY_CONNECTED; AFFINE_IMP_CONVEX] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `x:real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC CONNECTED_IMP_PERFECT_AFF_DIM THEN ASM_SIMP_TAC[AFFINE_IMP_CONVEX; CONVEX_CONNECTED] THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN ASM SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Basic properties of local compactness. *) (* ------------------------------------------------------------------------- *)
let LOCALLY_COMPACT = 
prove (`!s:real^N->bool. locally compact s <=> !x. x IN s ==> ?u v. x IN u /\ u SUBSET v /\ v SUBSET s /\ open_in (subtopology euclidean s) u /\ compact v`,
GEN_TAC THEN REWRITE_TAC[locally] THEN EQ_TAC THEN DISCH_TAC THENL [X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM (MP_TAC o SPECL [`s INTER ball(x:real^N,&1)`; `x:real^N`]) THEN ASM_SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL] THEN ASM_REWRITE_TAC[IN_INTER; CENTRE_IN_BALL; REAL_LT_01] THEN MESON_TAC[SUBSET_INTER]; MAP_EVERY X_GEN_TAC [`w:real^N->bool`; `x:real^N`] THEN REWRITE_TAC[IMP_CONJ] THEN GEN_REWRITE_TAC LAND_CONV [OPEN_IN_OPEN] THEN DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN ASM_REWRITE_TAC[IN_INTER] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `(s INTER ball(x:real^N,e)) INTER u` THEN EXISTS_TAC `cball(x:real^N,e) INTER v` THEN ASM_SIMP_TAC[OPEN_IN_INTER; OPEN_IN_OPEN_INTER; OPEN_BALL; CENTRE_IN_BALL; COMPACT_INTER; COMPACT_CBALL; IN_INTER] THEN MP_TAC(ISPECL [`x:real^N`; `e:real`] BALL_SUBSET_CBALL) THEN ASM SET_TAC[]]);;
let OPEN_IMP_LOCALLY_COMPACT = 
prove (`!s:real^N->bool. open s ==> locally compact s`,
REPEAT STRIP_TAC THEN REWRITE_TAC[LOCALLY_COMPACT] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_ASSUM (MP_TAC o GEN_REWRITE_RULE I [OPEN_CONTAINS_CBALL]) THEN DISCH_THEN(MP_TAC o SPEC `x:real^N`) THEN ANTS_TAC THENL [ASM_REWRITE_TAC[]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `e:real` STRIP_ASSUME_TAC) THEN MAP_EVERY EXISTS_TAC [`ball(x:real^N,e)`; `cball(x:real^N,e)`] THEN ASM_REWRITE_TAC[BALL_SUBSET_CBALL; CENTRE_IN_BALL; COMPACT_CBALL] THEN MATCH_MP_TAC OPEN_OPEN_IN_TRANS THEN ASM_REWRITE_TAC[OPEN_BALL] THEN ASM_MESON_TAC[BALL_SUBSET_CBALL; SUBSET_TRANS]);;
let CLOSED_IMP_LOCALLY_COMPACT = 
prove (`!s:real^N->bool. closed s ==> locally compact s`,
REPEAT STRIP_TAC THEN REWRITE_TAC[LOCALLY_COMPACT] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN MAP_EVERY EXISTS_TAC [`s INTER ball(x:real^N,&1)`; `s INTER cball(x:real^N,&1)`] THEN ASM_REWRITE_TAC[IN_INTER; CENTRE_IN_BALL; INTER_SUBSET; REAL_LT_01] THEN ASM_SIMP_TAC[OPEN_IN_OPEN_INTER; OPEN_BALL] THEN ASM_SIMP_TAC[CLOSED_INTER_COMPACT; COMPACT_CBALL] THEN MP_TAC(ISPECL [`x:real^N`; `&1`] BALL_SUBSET_CBALL) THEN ASM SET_TAC[]);;
let IS_INTERVAL_IMP_LOCALLY_COMPACT = 
prove (`!s:real^N->bool. is_interval s ==> locally compact s`,
REPEAT STRIP_TAC THEN REWRITE_TAC[LOCALLY_COMPACT] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN MP_TAC(ISPECL [`s:real^N->bool`; `x:real^N`] INTERVAL_CONTAINS_COMPACT_NEIGHBOURHOOD) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`; `d:real`] THEN STRIP_TAC THEN MAP_EVERY EXISTS_TAC [`s INTER ball(x:real^N,d)`; `interval[a:real^N,b]`] THEN ASM_SIMP_TAC[COMPACT_INTERVAL; OPEN_IN_OPEN_INTER; OPEN_BALL] THEN ASM_REWRITE_TAC[CENTRE_IN_BALL; IN_INTER] THEN ASM SET_TAC[]);;
let LOCALLY_COMPACT_UNIV = 
prove (`locally compact (:real^N)`,
let LOCALLY_COMPACT_INTER = 
prove (`!s t:real^N->bool. locally compact s /\ locally compact t ==> locally compact (s INTER t)`,
MATCH_MP_TAC LOCALLY_INTER THEN REWRITE_TAC[COMPACT_INTER]);;
let LOCALLY_COMPACT_OPEN_IN = 
prove (`!s t:real^N->bool. open_in (subtopology euclidean s) t /\ locally compact s ==> locally compact t`,
REWRITE_TAC[OPEN_IN_OPEN] THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[LOCALLY_COMPACT_INTER; OPEN_IMP_LOCALLY_COMPACT]);;
let LOCALLY_COMPACT_CLOSED_IN = 
prove (`!s t:real^N->bool. closed_in (subtopology euclidean s) t /\ locally compact s ==> locally compact t`,
REWRITE_TAC[CLOSED_IN_CLOSED] THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC[LOCALLY_COMPACT_INTER; CLOSED_IMP_LOCALLY_COMPACT]);;
let SIGMA_COMPACT = 
prove (`!s:real^N->bool. locally compact s ==> ?f. COUNTABLE f /\ (!t. t IN f ==> compact t) /\ UNIONS f = s`,
GEN_TAC THEN REWRITE_TAC[LOCALLY_COMPACT] THEN GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`u:real^N->real^N->bool`; `c:real^N->real^N->bool`] THEN DISCH_TAC THEN MP_TAC(ISPECL [`IMAGE (u:real^N->real^N->bool) s`; `s:real^N->bool`] LINDELOF_OPEN_IN) THEN ASM_SIMP_TAC[FORALL_IN_IMAGE] THEN ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> q /\ p /\ r`] THEN REWRITE_TAC[EXISTS_COUNTABLE_SUBSET_IMAGE] THEN DISCH_THEN(X_CHOOSE_THEN `t:real^N->bool` STRIP_ASSUME_TAC) THEN EXISTS_TAC `IMAGE (c:real^N->real^N->bool) t` THEN REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ; FORALL_IN_IMAGE; FORALL_IN_UNIONS] THEN ASM_SIMP_TAC[COUNTABLE_IMAGE] THEN ASM SET_TAC[]);;
let HOMEOMORPHIC_LOCAL_COMPACTNESS = 
prove (`!s t:real^N->bool. s homeomorphic t ==> (locally compact s <=> locally compact t)`,
MATCH_MP_TAC HOMEOMORPHIC_LOCALLY THEN REWRITE_TAC[HOMEOMORPHIC_COMPACTNESS]);;
let LOCALLY_COMPACT_TRANSLATION_EQ = 
prove (`!a:real^N s. locally compact (IMAGE (\x. a + x) s) <=> locally compact s`,
MATCH_MP_TAC LOCALLY_TRANSLATION THEN REWRITE_TAC[COMPACT_TRANSLATION_EQ]);;
add_translation_invariants [LOCALLY_COMPACT_TRANSLATION_EQ];;
let LOCALLY_COMPACT_LINEAR_IMAGE_EQ = 
prove (`!f:real^M->real^N s. linear f /\ (!x y. f x = f y ==> x = y) ==> (locally compact (IMAGE f s) <=> locally compact s)`,
MATCH_MP_TAC LOCALLY_INJECTIVE_LINEAR_IMAGE THEN REWRITE_TAC[COMPACT_LINEAR_IMAGE_EQ]);;
add_linear_invariants [LOCALLY_COMPACT_LINEAR_IMAGE_EQ];;
let LOCALLY_CLOSED = 
prove (`!s:real^N->bool. locally closed s <=> locally compact s`,
GEN_TAC THEN EQ_TAC THENL [ALL_TAC; MESON_TAC[LOCALLY_MONO; COMPACT_IMP_CLOSED]] THEN REWRITE_TAC[locally] THEN DISCH_TAC THEN MAP_EVERY X_GEN_TAC [`w:real^N->bool`; `x:real^N`] THEN STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL [`w:real^N->bool`; `x:real^N`]) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `v:real^N->bool`] THEN STRIP_TAC THEN EXISTS_TAC `u INTER ball(x:real^N,&1)` THEN EXISTS_TAC `v INTER cball(x:real^N,&1)` THEN ASM_SIMP_TAC[OPEN_IN_INTER_OPEN; OPEN_BALL] THEN ASM_SIMP_TAC[CLOSED_INTER_COMPACT; COMPACT_CBALL] THEN ASM_REWRITE_TAC[IN_INTER; CENTRE_IN_BALL; REAL_LT_01] THEN MP_TAC(ISPEC `x:real^N` BALL_SUBSET_CBALL) THEN ASM SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Locally compact sets are closed in an open set and are homeomorphic *) (* to an absolutely closed set if we have one more dimension to play with. *) (* ------------------------------------------------------------------------- *)
let LOCALLY_COMPACT_OPEN_INTER_CLOSURE = 
prove (`!s:real^N->bool. locally compact s ==> ?t. open t /\ s = t INTER closure s`,
GEN_TAC THEN SIMP_TAC[LOCALLY_COMPACT; OPEN_IN_OPEN; CLOSED_IN_CLOSED] THEN REWRITE_TAC[LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN REWRITE_TAC[GSYM CONJ_ASSOC; TAUT `p /\ x = y /\ q <=> x = y /\ p /\ q`] THEN ONCE_REWRITE_TAC[MESON[] `(?a b c. P a b c) <=> (?c b a. P a b c)`] THEN REWRITE_TAC[UNWIND_THM2] THEN GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV) [RIGHT_IMP_EXISTS_THM] THEN REWRITE_TAC[SKOLEM_THM; LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`u:real^N->real^N->bool`; `v:real^N->real^N->bool`] THEN DISCH_TAC THEN EXISTS_TAC `UNIONS (IMAGE (u:real^N->real^N->bool) s)` THEN ASM_SIMP_TAC[CLOSED_CLOSURE; OPEN_UNIONS; FORALL_IN_IMAGE] THEN REWRITE_TAC[INTER_UNIONS] THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `UNIONS {v INTER s | v | v IN IMAGE (u:real^N->real^N->bool) s}` THEN CONJ_TAC THENL [SIMP_TAC[UNIONS_GSPEC; EXISTS_IN_IMAGE] THEN ASM SET_TAC[]; ALL_TAC] THEN AP_TERM_TAC THEN MATCH_MP_TAC(SET_RULE `(!x. x IN s ==> f(g x) = f'(g x)) ==> {f x | x IN IMAGE g s} = {f' x | x IN IMAGE g s}`) THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN REWRITE_TAC[GSYM SUBSET_ANTISYM_EQ] THEN CONJ_TAC THENL [MP_TAC(ISPEC `s:real^N->bool` CLOSURE_SUBSET) THEN ASM SET_TAC[]; REWRITE_TAC[SUBSET_INTER; INTER_SUBSET] THEN MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `closure((u:real^N->real^N->bool) x INTER s)` THEN ASM_SIMP_TAC[OPEN_INTER_CLOSURE_SUBSET] THEN MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `(v:real^N->real^N->bool) x` THEN ASM_SIMP_TAC[] THEN MATCH_MP_TAC CLOSURE_MINIMAL THEN ASM_SIMP_TAC[COMPACT_IMP_CLOSED] THEN ASM SET_TAC[]]);;
let LOCALLY_COMPACT_CLOSED_IN_OPEN = 
prove (`!s:real^N->bool. locally compact s ==> ?t. open t /\ closed_in (subtopology euclidean t) s`,
GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP LOCALLY_COMPACT_OPEN_INTER_CLOSURE) THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `t:real^N->bool` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_X_ASSUM SUBST1_TAC THEN SIMP_TAC[CLOSED_IN_CLOSED_INTER; CLOSED_CLOSURE]);;
let LOCALLY_COMPACT_HOMEOMORPHISM_PROJECTION_CLOSED = 
prove (`!s:real^M->bool. locally compact s ==> ?t:real^(M,N)finite_sum->bool f. closed t /\ homeomorphism (s,t) (f,fstcart)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `closed(s:real^M->bool)` THENL [EXISTS_TAC `(s:real^M->bool) PCROSS {vec 0:real^N}` THEN EXISTS_TAC `\x. (pastecart x (vec 0):real^(M,N)finite_sum)` THEN ASM_SIMP_TAC[CLOSED_PCROSS; CLOSED_SING; HOMEOMORPHISM] THEN SIMP_TAC[CONTINUOUS_ON_PASTECART; CONTINUOUS_ON_CONST; CONTINUOUS_ON_ID; LINEAR_FSTCART; LINEAR_CONTINUOUS_ON; SUBSET; FORALL_IN_IMAGE] THEN REWRITE_TAC[FORALL_IN_PCROSS; PASTECART_IN_PCROSS; IN_SING] THEN SIMP_TAC[FSTCART_PASTECART]; ALL_TAC] THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP LOCALLY_COMPACT_OPEN_INTER_CLOSURE) THEN DISCH_THEN(X_CHOOSE_THEN `t:real^M->bool` (STRIP_ASSUME_TAC o GSYM)) THEN DISJ_CASES_TAC(SET_RULE `t = (:real^M) \/ ~((:real^M) DIFF t = {})`) THENL [ASM_MESON_TAC[CLOSURE_EQ; INTER_UNIV]; ALL_TAC] THEN ABBREV_TAC `f:real^M->real^(M,N)finite_sum = \x. pastecart x (inv(setdist({x},(:real^M) DIFF t)) % vec 1)` THEN SUBGOAL_THEN `homeomorphism (t,IMAGE (f:real^M->real^(M,N)finite_sum) t) (f,fstcart)` ASSUME_TAC THENL [SIMP_TAC[HOMEOMORPHISM; SUBSET_REFL; LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; FORALL_IN_IMAGE] THEN MATCH_MP_TAC(TAUT `(r ==> q /\ s) /\ r /\ p ==> p /\ q /\ r /\ s`) THEN CONJ_TAC THENL [SET_TAC[]; EXPAND_TAC "f"] THEN SIMP_TAC[FSTCART_PASTECART] THEN MATCH_MP_TAC CONTINUOUS_ON_PASTECART THEN REWRITE_TAC[CONTINUOUS_ON_ID] THEN MATCH_MP_TAC CONTINUOUS_ON_MUL THEN REWRITE_TAC[o_DEF; CONTINUOUS_ON_CONST] THEN MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_ON_INV) THEN REWRITE_TAC[SETDIST_EQ_0_SING; CONTINUOUS_ON_LIFT_SETDIST] THEN ASM_SIMP_TAC[CLOSURE_COMPLEMENT; IN_DIFF; IN_UNIV; INTERIOR_OPEN]; ALL_TAC] THEN EXISTS_TAC `IMAGE (f:real^M->real^(M,N)finite_sum) s` THEN EXISTS_TAC `f:real^M->real^(M,N)finite_sum` THEN CONJ_TAC THENL [MATCH_MP_TAC CLOSED_IN_CLOSED_TRANS THEN EXISTS_TAC `IMAGE (f:real^M->real^(M,N)finite_sum) t` THEN CONJ_TAC THENL [MATCH_MP_TAC HOMEOMORPHISM_IMP_CLOSED_MAP THEN MAP_EVERY EXISTS_TAC [`fstcart:real^(M,N)finite_sum->real^M`; `t:real^M->bool`] THEN ASM_REWRITE_TAC[] THEN EXPAND_TAC "s" THEN SIMP_TAC[CLOSED_IN_CLOSED_INTER; CLOSED_CLOSURE]; SUBGOAL_THEN `IMAGE (f:real^M->real^(M,N)finite_sum) t = {z | (setdist({fstcart z},(:real^M) DIFF t) % sndcart z) IN {vec 1}}` SUBST1_TAC THENL [EXPAND_TAC "f" THEN REWRITE_TAC[EXTENSION; FORALL_PASTECART; IN_ELIM_THM; PASTECART_INJ; FSTCART_PASTECART; SNDCART_PASTECART; IN_IMAGE; IN_INTER; GSYM CONJ_ASSOC; UNWIND_THM1; IN_SING] THEN REWRITE_TAC[CART_EQ; VECTOR_MUL_COMPONENT; VEC_COMPONENT] THEN MAP_EVERY X_GEN_TAC [`x:real^M`; `y:real^N`] THEN MP_TAC(ISPECL [`(:real^M) DIFF t`; `x:real^M`] (CONJUNCT1 SETDIST_EQ_0_SING)) THEN ASM_SIMP_TAC[CLOSURE_COMPLEMENT; IN_DIFF; IN_UNIV; INTERIOR_OPEN] THEN ASM_CASES_TAC `(x:real^M) IN t` THEN ASM_SIMP_TAC[REAL_FIELD `~(x = &0) ==> (y = inv x * &1 <=> x * y = &1)`] THEN DISCH_TAC THEN DISCH_THEN(MP_TAC o SPEC `1`) THEN REWRITE_TAC[LE_REFL; DIMINDEX_GE_1] THEN REAL_ARITH_TAC; MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE_UNIV THEN REWRITE_TAC[CLOSED_SING] THEN X_GEN_TAC `z:real^(M,N)finite_sum` THEN MATCH_MP_TAC CONTINUOUS_MUL THEN SIMP_TAC[LINEAR_CONTINUOUS_AT; LINEAR_SNDCART; o_DEF] THEN SUBGOAL_THEN `(\z:real^(M,N)finite_sum. lift(setdist({fstcart z},(:real^M) DIFF t))) = (\x. lift (setdist ({x},(:real^M) DIFF t))) o fstcart` SUBST1_TAC THENL [REWRITE_TAC[o_DEF]; ALL_TAC] THEN MATCH_MP_TAC CONTINUOUS_AT_COMPOSE THEN SIMP_TAC[LINEAR_CONTINUOUS_AT; LINEAR_FSTCART] THEN REWRITE_TAC[CONTINUOUS_AT_LIFT_SETDIST]]]; MATCH_MP_TAC HOMEOMORPHISM_OF_SUBSETS THEN MAP_EVERY EXISTS_TAC [`t:real^M->bool`; `IMAGE (f:real^M->real^(M,N)finite_sum) t`] THEN ASM SET_TAC[]]);;
let LOCALLY_COMPACT_HOMEOMORPHIC_CLOSED = 
prove (`!s:real^M->bool. locally compact s /\ dimindex(:M) < dimindex(:N) ==> ?t:real^N->bool. closed t /\ s homeomorphic t`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `?t:real^(M,1)finite_sum->bool h. closed t /\ homeomorphism (s,t) (h,fstcart)` STRIP_ASSUME_TAC THENL [ASM_SIMP_TAC[LOCALLY_COMPACT_HOMEOMORPHISM_PROJECTION_CLOSED]; ALL_TAC] THEN ABBREV_TAC `f:real^(M,1)finite_sum->real^N = \x. lambda i. if i <= dimindex(:M) then x$i else x$(dimindex(:M)+1)` THEN ABBREV_TAC `g:real^N->real^(M,1)finite_sum = (\x. lambda i. x$i)` THEN EXISTS_TAC `IMAGE (f:real^(M,1)finite_sum->real^N) t` THEN SUBGOAL_THEN `linear(f:real^(M,1)finite_sum->real^N)` ASSUME_TAC THENL [EXPAND_TAC "f" THEN REWRITE_TAC[linear; CART_EQ] THEN SIMP_TAC[LAMBDA_BETA; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN MESON_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `linear(g:real^N->real^(M,1)finite_sum)` ASSUME_TAC THENL [EXPAND_TAC "g" THEN REWRITE_TAC[linear; CART_EQ] THEN SIMP_TAC[LAMBDA_BETA; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT] THEN MESON_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `!x. (g:real^N->real^(M,1)finite_sum)((f:real^(M,1)finite_sum->real^N) x) = x` ASSUME_TAC THENL [MAP_EVERY EXPAND_TAC ["f";
"g"] THEN FIRST_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE `m < n ==> !i. i <= m + 1 ==> i <= n`)) THEN SIMP_TAC[CART_EQ; LAMBDA_BETA; DIMINDEX_FINITE_SUM; DIMINDEX_1] THEN REWRITE_TAC[ARITH_RULE `i <= n + 1 <=> i <= n \/ i = n + 1`] THEN MESON_TAC[]; ALL_TAC] THEN CONJ_TAC THENL [ASM_MESON_TAC[CLOSED_INJECTIVE_LINEAR_IMAGE]; ALL_TAC] THEN TRANS_TAC HOMEOMORPHIC_TRANS `t:real^(M,1)finite_sum->bool` THEN CONJ_TAC THENL [ASM_MESON_TAC[homeomorphic]; ALL_TAC] THEN REWRITE_TAC[homeomorphic; HOMEOMORPHISM] THEN MAP_EVERY EXISTS_TAC [`f:real^(M,1)finite_sum->real^N`; `g:real^N->real^(M,1)finite_sum`] THEN ASM_SIMP_TAC[LINEAR_CONTINUOUS_ON] THEN ASM SET_TAC[]);; (* ------------------------------------------------------------------------- *) (* Relations between components and path components. *) (* ------------------------------------------------------------------------- *)
let OPEN_CONNECTED_COMPONENT = 
prove (`!s x:real^N. open s ==> open(connected_component s x)`,
REPEAT GEN_TAC THEN REWRITE_TAC[OPEN_CONTAINS_BALL] THEN DISCH_TAC THEN X_GEN_TAC `y:real^N` THEN DISCH_TAC THEN FIRST_X_ASSUM(MP_TAC o SPEC `y:real^N`) THEN ANTS_TAC THENL [ASM_MESON_TAC[SUBSET; CONNECTED_COMPONENT_SUBSET]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `e:real` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `connected_component s (x:real^N) = connected_component s y` SUBST1_TAC THENL [ASM_MESON_TAC[CONNECTED_COMPONENT_EQ]; MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[CENTRE_IN_BALL; CONNECTED_BALL]]);;
let IN_CLOSURE_CONNECTED_COMPONENT = 
prove (`!x y:real^N. x IN s /\ open s ==> (x IN closure(connected_component s y) <=> x IN connected_component s y)`,
REPEAT STRIP_TAC THEN EQ_TAC THEN REWRITE_TAC[REWRITE_RULE[SUBSET] CLOSURE_SUBSET] THEN DISCH_TAC THEN SUBGOAL_THEN `~((connected_component s (x:real^N)) INTER closure(connected_component s y) = {})` MP_TAC THENL [REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `x:real^N` THEN ASM_REWRITE_TAC[IN_INTER] THEN ASM_REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ]; ASM_SIMP_TAC[OPEN_INTER_CLOSURE_EQ_EMPTY; OPEN_CONNECTED_COMPONENT] THEN REWRITE_TAC[CONNECTED_COMPONENT_OVERLAP] THEN STRIP_TAC THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN ASM_REWRITE_TAC[IN; CONNECTED_COMPONENT_REFL_EQ]]);;
let PATH_COMPONENT_SUBSET_CONNECTED_COMPONENT = 
prove (`!s x:real^N. (path_component s x) SUBSET (connected_component s x)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THENL [MATCH_MP_TAC CONNECTED_COMPONENT_MAXIMAL THEN ASM_REWRITE_TAC[PATH_COMPONENT_SUBSET; IN; PATH_COMPONENT_REFL_EQ] THEN SIMP_TAC[PATH_CONNECTED_IMP_CONNECTED; PATH_CONNECTED_PATH_COMPONENT]; ASM_MESON_TAC[PATH_COMPONENT_EQ_EMPTY; SUBSET_REFL; CONNECTED_COMPONENT_EQ_EMPTY]]);;
let PATH_COMPONENT_EQ_CONNECTED_COMPONENT = 
prove (`!s x:real^N. locally path_connected s ==> (path_component s x = connected_component s x)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x:real^N) IN s` THENL [ALL_TAC; ASM_MESON_TAC[PATH_COMPONENT_EQ_EMPTY; CONNECTED_COMPONENT_EQ_EMPTY]] THEN MP_TAC(ISPECL[`s:real^N->bool`; `x:real^N`] CONNECTED_CONNECTED_COMPONENT) THEN REWRITE_TAC[CONNECTED_CLOPEN] THEN REWRITE_TAC[TAUT `p ==> q \/ r <=> p /\ ~q ==> r`] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[PATH_COMPONENT_EQ_EMPTY] THEN CONJ_TAC THENL [MATCH_MP_TAC OPEN_IN_SUBSET_TRANS; MATCH_MP_TAC CLOSED_IN_SUBSET_TRANS] THEN EXISTS_TAC `s:real^N->bool` THEN ASM_SIMP_TAC[OPEN_IN_PATH_COMPONENT_LOCALLY_PATH_CONNECTED; CLOSED_IN_PATH_COMPONENT_LOCALLY_PATH_CONNECTED; PATH_COMPONENT_SUBSET_CONNECTED_COMPONENT; CONNECTED_COMPONENT_SUBSET]);;
let LOCALLY_PATH_CONNECTED_PATH_COMPONENT = 
prove (`!s x:real^N. locally path_connected s ==> locally path_connected (path_component s x)`,
let OPEN_PATH_CONNECTED_COMPONENT = 
prove (`!s x:real^N. open s ==> path_component s x = connected_component s x`,
let PATH_CONNECTED_EQ_CONNECTED_LPC = 
prove (`!s. locally path_connected s ==> (path_connected s <=> connected s)`,
let PATH_CONNECTED_EQ_CONNECTED = 
prove (`!s. open s ==> (path_connected s <=> connected s)`,
let CONNECTED_OPEN_PATH_CONNECTED = 
prove (`!s:real^N->bool. open s /\ connected s ==> path_connected s`,
let CONNECTED_OPEN_ARC_CONNECTED = 
prove (`!s:real^N->bool. open s /\ connected s ==> !x y. x IN s /\ y IN s ==> x = y \/ ?g. arc g /\ path_image g SUBSET s /\ pathstart g = x /\ pathfinish g = y`,
GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP CONNECTED_OPEN_PATH_CONNECTED) THEN REWRITE_TAC[PATH_CONNECTED_ARCWISE] THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN MESON_TAC[]);;
let OPEN_COMPONENTS = 
prove (`!u:real^N->bool s. open u /\ s IN components u ==> open s`,
REPEAT STRIP_TAC THEN STRIP_ASSUME_TAC (MESON[IN_COMPONENTS; ASSUME `s:real^N->bool IN components u`] `?x. s:real^N->bool = connected_component u x`) THEN ASM_SIMP_TAC [OPEN_CONNECTED_COMPONENT]);;
let COMPONENTS_OPEN_UNIQUE = 
prove (`!f:(real^N->bool)->bool s. (!c. c IN f ==> open c /\ connected c /\ ~(c = {})) /\ pairwise DISJOINT f /\ UNIONS f = s ==> components s = f`,
let CONTINUOUS_ON_COMPONENTS = 
prove (`!f:real^M->real^N s. open s /\ (!c. c IN components s ==> f continuous_on c) ==> f continuous_on s`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC CONTINUOUS_ON_COMPONENTS_GEN THEN ASM_SIMP_TAC[] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC OPEN_SUBSET THEN ASM_MESON_TAC[OPEN_COMPONENTS; IN_COMPONENTS_SUBSET]);;
let CONTINUOUS_ON_COMPONENTS_EQ = 
prove (`!f s. open s ==> (f continuous_on s <=> !c. c IN components s ==> f continuous_on c)`,
REPEAT STRIP_TAC THEN EQ_TAC THENL [MESON_TAC[CONTINUOUS_ON_SUBSET; IN_COMPONENTS_SUBSET]; ASM_MESON_TAC[CONTINUOUS_ON_COMPONENTS]]);;
let CLOSED_IN_UNION_COMPLEMENT_COMPONENT = 
prove (`!u s c:real^N->bool. locally connected u /\ closed_in (subtopology euclidean u) s /\ c IN components(u DIFF s) ==> closed_in (subtopology euclidean u) (s UNION c)`,
REPEAT STRIP_TAC THEN SUBGOAL_THEN `s UNION c:real^N->bool = u DIFF (UNIONS(components(u DIFF s) DELETE c))` SUBST1_TAC THENL [MP_TAC(ISPEC `(u:real^N->bool) DIFF s` UNIONS_COMPONENTS) THEN ONCE_REWRITE_TAC [EXTENSION] THEN REWRITE_TAC[IN_UNION; IN_UNIV; IN_UNIONS; IN_DELETE; IN_DIFF] THEN MP_TAC(ISPEC `(u:real^N->bool) DIFF s` PAIRWISE_DISJOINT_COMPONENTS) THEN REWRITE_TAC[pairwise; SET_RULE `DISJOINT s t <=> !x. ~(x IN s /\ x IN t)`] THEN FIRST_ASSUM(MP_TAC o MATCH_MP CLOSED_IN_IMP_SUBSET) THEN FIRST_ASSUM(MP_TAC o MATCH_MP IN_COMPONENTS_SUBSET) THEN REWRITE_TAC[SUBSET] THEN ASM_MESON_TAC[]; REWRITE_TAC[closed_in; TOPSPACE_EUCLIDEAN_SUBTOPOLOGY; SUBSET_DIFF] THEN MATCH_MP_TAC OPEN_IN_DIFF THEN REWRITE_TAC[OPEN_IN_REFL] THEN MATCH_MP_TAC CLOSED_IN_DIFF THEN REWRITE_TAC[CLOSED_IN_REFL] THEN MATCH_MP_TAC OPEN_IN_UNIONS THEN REWRITE_TAC[IN_DELETE] THEN X_GEN_TAC `d:real^N->bool` THEN STRIP_TAC THEN MATCH_MP_TAC OPEN_IN_TRANS THEN EXISTS_TAC `u DIFF s:real^N->bool` THEN CONJ_TAC THENL [MATCH_MP_TAC OPEN_IN_COMPONENTS_LOCALLY_CONNECTED THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC LOCALLY_OPEN_SUBSET THEN EXISTS_TAC `u:real^N->bool` THEN ASM_REWRITE_TAC[]; ALL_TAC] THEN MATCH_MP_TAC OPEN_IN_DIFF THEN ASM_SIMP_TAC[OPEN_IN_REFL]]);;
let CLOSED_UNION_COMPLEMENT_COMPONENT = 
prove (`!s c. closed s /\ c IN components((:real^N) DIFF s) ==> closed(s UNION c)`,
ONCE_REWRITE_TAC[CLOSED_IN] THEN ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_UNIV] THEN REPEAT STRIP_TAC THEN MATCH_MP_TAC CLOSED_IN_UNION_COMPLEMENT_COMPONENT THEN ASM_REWRITE_TAC[LOCALLY_CONNECTED_UNIV]);;
let COUNTABLE_COMPONENTS = 
prove (`!s:real^N->bool. open s ==> COUNTABLE(components s)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC COUNTABLE_DISJOINT_OPEN_SUBSETS THEN REWRITE_TAC[PAIRWISE_DISJOINT_COMPONENTS] THEN ASM_MESON_TAC[OPEN_COMPONENTS]);;
let FRONTIER_MINIMAL_SEPARATING_CLOSED = 
prove (`!s c. closed s /\ ~connected((:real^N) DIFF s) /\ (!t. closed t /\ t PSUBSET s ==> connected((:real^N) DIFF t)) /\ c IN components ((:real^N) DIFF s) ==> frontier c = s`,
REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE RAND_CONV [CONNECTED_EQ_CONNECTED_COMPONENTS_EQ]) THEN DISCH_THEN(MP_TAC o MATCH_MP (MESON[] `~(!x x'. x IN s /\ x' IN s ==> x = x') ==> !x. x IN s ==> ?y. y IN s /\ ~(y = x)`)) THEN DISCH_THEN(MP_TAC o SPEC `c:real^N->bool`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `d:real^N->bool` STRIP_ASSUME_TAC) THEN FIRST_X_ASSUM(MP_TAC o SPEC `frontier c:real^N->bool`) THEN REWRITE_TAC[SET_RULE `s PSUBSET t <=> s SUBSET t /\ ~(t SUBSET s)`; GSYM SUBSET_ANTISYM_EQ] THEN ASM_SIMP_TAC[FRONTIER_OF_COMPONENTS_CLOSED_COMPLEMENT; FRONTIER_CLOSED] THEN MATCH_MP_TAC(TAUT `~r ==> (~p ==> r) ==> p`) THEN REWRITE_TAC[connected] THEN MAP_EVERY EXISTS_TAC [`c:real^N->bool`; `(:real^N) DIFF closure c`] THEN REPEAT CONJ_TAC THENL [ASM_MESON_TAC[OPEN_COMPONENTS; closed]; REWRITE_TAC[GSYM closed; CLOSED_CLOSURE]; MP_TAC(ISPEC `c:real^N->bool` INTERIOR_SUBSET) THEN REWRITE_TAC[frontier] THEN SET_TAC[]; MATCH_MP_TAC(SET_RULE `c SUBSET c' ==> c INTER (UNIV DIFF c') INTER s = {}`) THEN REWRITE_TAC[GSYM INTERIOR_COMPLEMENT; CLOSURE_SUBSET]; REWRITE_TAC[frontier] THEN MATCH_MP_TAC(SET_RULE `ci = c /\ ~(c = {}) ==> ~(c INTER (UNIV DIFF (cc DIFF ci)) = {})`) THEN ASM_MESON_TAC[IN_COMPONENTS_NONEMPTY; INTERIOR_OPEN; closed; OPEN_COMPONENTS]; REWRITE_TAC[frontier] THEN MATCH_MP_TAC(SET_RULE `~(UNIV DIFF c = {}) ==> ~((UNIV DIFF c) INTER (UNIV DIFF (c DIFF i)) = {})`) THEN REWRITE_TAC[GSYM INTERIOR_COMPLEMENT] THEN MATCH_MP_TAC(SET_RULE `!t. t SUBSET s /\ ~(t = {}) ==> ~(s = {})`) THEN EXISTS_TAC `d:real^N->bool` THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[IN_COMPONENTS_NONEMPTY]] THEN MATCH_MP_TAC INTERIOR_MAXIMAL THEN REWRITE_TAC[SET_RULE `s SUBSET UNIV DIFF t <=> s INTER t = {}`] THEN ASM_MESON_TAC[COMPONENTS_NONOVERLAP; OPEN_COMPONENTS; GSYM closed]]);;
(* ------------------------------------------------------------------------- *) (* Lower bound on norms within segment between vectors. *) (* Could have used these for connectedness results below, in fact. *) (* ------------------------------------------------------------------------- *)
let NORM_SEGMENT_LOWERBOUND = 
prove (`!a b x:real^N r d. &0 < r /\ norm(a) = r /\ norm(b) = r /\ x IN segment[a,b] /\ a dot b = d * r pow 2 ==> sqrt((&1 - abs d) / &2) * r <= norm(x)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[GSYM real_ge] THEN REWRITE_TAC[NORM_GE_SQUARE] THEN DISJ2_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN ASM_REWRITE_TAC[real_ge; DOT_LMUL; DOT_RMUL; REAL_MUL_RZERO; VECTOR_ARITH `(a + b) dot (a + b) = a dot a + b dot b + &2 * a dot b`] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(&1 - u) * (&1 - u) * r pow 2 + u * u * r pow 2 - &2 * (&1 - u) * u * abs d * r pow 2` THEN CONJ_TAC THENL [REWRITE_TAC[REAL_POW_MUL; REAL_MUL_ASSOC] THEN REWRITE_TAC[GSYM REAL_ADD_RDISTRIB; GSYM REAL_SUB_RDISTRIB] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_POW_2; REAL_LE_SQUARE] THEN REWRITE_TAC[GSYM REAL_POW_2; REAL_ARITH `(&1 - u) pow 2 + u pow 2 - ((&2 * (&1 - u)) * u) * d = (&1 + d) * (&1 - &2 * u + &2 * u pow 2) - d`] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(&1 + abs d) * &1 / &2 - abs d` THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ARITH `(&1 + d) * &1 / &2 - d = (&1 - d) / &2`] THEN MATCH_MP_TAC REAL_EQ_IMP_LE THEN MATCH_MP_TAC SQRT_POW_2 THEN MP_TAC(ISPECL [`a:real^N`; `b:real^N`] NORM_CAUCHY_SCHWARZ_ABS) THEN ASM_REWRITE_TAC[REAL_ABS_MUL; REAL_ABS_POW; REAL_POW2_ABS] THEN ASM_REWRITE_TAC[REAL_ARITH `r * r = &1 * r pow 2`] THEN ASM_SIMP_TAC[REAL_LE_RMUL_EQ; REAL_POW_LT] THEN REAL_ARITH_TAC; MATCH_MP_TAC(REAL_ARITH `x <= y ==> x - a <= y - a`) THEN MATCH_MP_TAC REAL_LE_LMUL THEN CONJ_TAC THENL [REAL_ARITH_TAC; MATCH_MP_TAC(REAL_ARITH `&0 <= (u - &1 / &2) * (u - &1 / &2) ==> &1 / &2 <= &1 - &2 * u + &2 * u pow 2`) THEN REWRITE_TAC[REAL_LE_SQUARE]]]; ASM_REWRITE_TAC[GSYM NORM_POW_2; REAL_LE_LADD; real_sub] THEN MATCH_MP_TAC(REAL_ARITH `abs(a) <= --x ==> x <= a`) THEN ASM_REWRITE_TAC[REAL_ABS_MUL; REAL_MUL_LNEG; REAL_NEG_NEG] THEN REWRITE_TAC[REAL_ABS_POW; REAL_POW2_ABS; REAL_ABS_NUM] THEN REWRITE_TAC[REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_POW_2; REAL_LE_SQUARE] THEN ASM_REWRITE_TAC[real_abs; GSYM real_sub; REAL_SUB_LE; REAL_POS] THEN MATCH_MP_TAC REAL_LE_LMUL THEN CONJ_TAC THEN REPEAT(MATCH_MP_TAC REAL_LE_MUL THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC]);;
(* ------------------------------------------------------------------------- *) (* Special case of orthogonality (could replace 2 by sqrt(2)). *) (* ------------------------------------------------------------------------- *)
let NORM_SEGMENT_ORTHOGONAL_LOWERBOUND = 
prove (`!a b:real^N x r. r <= norm(a) /\ r <= norm(b) /\ orthogonal a b /\ x IN segment[a,b] ==> r / &2 <= norm(x)`,
REPEAT GEN_TAC THEN REWRITE_TAC[GSYM real_ge] THEN REWRITE_TAC[NORM_GE_SQUARE] THEN REWRITE_TAC[real_ge] THEN ASM_CASES_TAC `r <= &0` THEN ASM_REWRITE_TAC[] THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN REWRITE_TAC[orthogonal] THEN STRIP_TAC THEN DISJ2_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_SEGMENT]) THEN DISCH_THEN(X_CHOOSE_THEN `u:real` STRIP_ASSUME_TAC) THEN ASM_REWRITE_TAC[DOT_LMUL; DOT_RMUL; REAL_MUL_RZERO; VECTOR_ARITH `(a + b) dot (a + b) = a dot a + b dot b + &2 * a dot b`] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `(&1 - u) * (&1 - u) * r pow 2 + u * u * r pow 2` THEN CONJ_TAC THENL [REWRITE_TAC[REAL_ARITH `(r / &2) pow 2 = &1 / &4 * r pow 2`] THEN REWRITE_TAC[GSYM REAL_ADD_RDISTRIB; REAL_MUL_ASSOC] THEN MATCH_MP_TAC REAL_LE_RMUL THEN REWRITE_TAC[REAL_POW_2; REAL_LE_SQUARE] THEN MATCH_MP_TAC(REAL_ARITH `&0 <= (u - &1 / &2) * (u - &1 / &2) ==> &1 / &4 <= (&1 - u) * (&1 - u) + u * u`) THEN REWRITE_TAC[REAL_LE_SQUARE]; REWRITE_TAC[REAL_ADD_RID] THEN MATCH_MP_TAC REAL_LE_ADD2 THEN CONJ_TAC THEN REPEAT(MATCH_MP_TAC REAL_LE_LMUL THEN CONJ_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC]) THEN ASM_REWRITE_TAC[]]);;
(* ------------------------------------------------------------------------- *) (* Accessibility of frontier points. *) (* ------------------------------------------------------------------------- *)
let DENSE_ACCESSIBLE_FRONTIER_POINTS = 
prove (`!s:real^N->bool v. open s /\ open_in (subtopology euclidean (frontier s)) v /\ ~(v = {}) ==> ?g. arc g /\ IMAGE g (interval [vec 0,vec 1] DELETE vec 1) SUBSET s /\ pathstart g IN s /\ pathfinish g IN v`,
REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN DISCH_THEN(X_CHOOSE_TAC `z:real^N`) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_CONTAINS_BALL]) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `z:real^N`)) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `r:real` THEN STRIP_TAC THEN SUBGOAL_THEN `(z:real^N) IN frontier s` MP_TAC THENL [ASM SET_TAC[]; DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN REWRITE_TAC[frontier] THEN ASM_SIMP_TAC[IN_DIFF; INTERIOR_OPEN]] THEN REWRITE_TAC[closure; IN_UNION; TAUT `(p \/ q) /\ ~p <=> ~p /\ q`] THEN REWRITE_TAC[IN_ELIM_THM] THEN STRIP_TAC THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [LIMPT_INFINITE_BALL]) THEN DISCH_THEN(MP_TAC o SPEC `r:real`) THEN ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `s INTER ball(z:real^N,r) = {}` THENL [ASM_MESON_TAC[INFINITE; FINITE_EMPTY]; DISCH_THEN(K ALL_TAC)] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN REWRITE_TAC[IN_INTER] THEN DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `~((y:real^N) IN frontier s)` ASSUME_TAC THENL [ASM_SIMP_TAC[IN_DIFF; INTERIOR_OPEN; frontier]; ALL_TAC] THEN SUBGOAL_THEN `path_connected(ball(z:real^N,r))` MP_TAC THENL [ASM_SIMP_TAC[CONVEX_BALL; CONVEX_IMP_PATH_CONNECTED]; ALL_TAC] THEN REWRITE_TAC[PATH_CONNECTED_ARCWISE] THEN DISCH_THEN(MP_TAC o SPECL [`y:real^N`; `z:real^N`]) THEN ASM_REWRITE_TAC[CENTRE_IN_BALL] THEN ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN DISCH_THEN(X_CHOOSE_THEN `g:real^1->real^N` STRIP_ASSUME_TAC) THEN MP_TAC(ISPEC `IMAGE drop {t | t IN interval[vec 0,vec 1] /\ (g:real^1->real^N) t IN frontier s}` COMPACT_ATTAINS_INF) THEN REWRITE_TAC[EXISTS_IN_IMAGE; IMAGE_EQ_EMPTY; FORALL_IN_IMAGE; IMP_CONJ] THEN REWRITE_TAC[IMP_IMP; FORALL_IN_GSPEC; EXISTS_IN_GSPEC; GSYM IMAGE_o] THEN REWRITE_TAC[o_DEF; LIFT_DROP; IMAGE_ID] THEN ANTS_TAC THENL [CONJ_TAC THENL [REWRITE_TAC[COMPACT_EQ_BOUNDED_CLOSED] THEN CONJ_TAC THENL [MATCH_MP_TAC BOUNDED_SUBSET THEN EXISTS_TAC `interval[vec 0:real^1,vec 1]` THEN REWRITE_TAC[BOUNDED_INTERVAL; SUBSET_RESTRICT]; MATCH_MP_TAC CONTINUOUS_CLOSED_PREIMAGE THEN REWRITE_TAC[FRONTIER_CLOSED; CLOSED_INTERVAL; GSYM path] THEN ASM_MESON_TAC[arc]]; REWRITE_TAC[GSYM MEMBER_NOT_EMPTY] THEN EXISTS_TAC `vec 1:real^1` THEN ASM_REWRITE_TAC[IN_ELIM_THM; ENDS_IN_UNIT_INTERVAL] THEN ASM_MESON_TAC[pathfinish; SUBSET]]; DISCH_THEN(X_CHOOSE_THEN `t:real^1` STRIP_ASSUME_TAC) THEN EXISTS_TAC `subpath (vec 0) t (g:real^1->real^N)` THEN ASM_REWRITE_TAC[PATHSTART_SUBPATH; PATHFINISH_SUBPATH] THEN MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL [MATCH_MP_TAC ARC_SUBPATH_ARC THEN ASM_REWRITE_TAC[ENDS_IN_UNIT_INTERVAL] THEN ASM_MESON_TAC[pathstart]; REWRITE_TAC[arc] THEN STRIP_TAC] THEN GEN_REWRITE_TAC (RAND_CONV o LAND_CONV o LAND_CONV) [GSYM pathstart] THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; RULE_ASSUM_TAC(SIMP_RULE[path_image]) THEN ASM SET_TAC[]] THEN MATCH_MP_TAC(SET_RULE `a IN s /\ IMAGE f s DELETE (f a) SUBSET t /\ (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) ==> IMAGE f (s DELETE a) SUBSET t`) THEN ASM_REWRITE_TAC[ENDS_IN_UNIT_INTERVAL; GSYM path_image] THEN W(MP_TAC o PART_MATCH (lhand o rand) PATH_IMAGE_SUBPATH o lhand o lhand o snd) THEN ANTS_TAC THENL [ASM_MESON_TAC[IN_INTERVAL_1]; DISCH_THEN SUBST1_TAC] THEN REWRITE_TAC[REWRITE_RULE[pathfinish] PATHFINISH_SUBPATH] THEN MATCH_MP_TAC(SET_RULE `IMAGE f (s DELETE a) DIFF t = {} ==> IMAGE f s DELETE f a SUBSET t`) THEN MATCH_MP_TAC(REWRITE_RULE[TAUT `p /\ q /\ ~r ==> ~s <=> p /\ q /\ s ==> r`] CONNECTED_INTER_FRONTIER) THEN REPEAT CONJ_TAC THENL [MATCH_MP_TAC CONNECTED_CONTINUOUS_IMAGE THEN CONJ_TAC THENL [FIRST_X_ASSUM(MP_TAC o CONJUNCT1 o GEN_REWRITE_RULE I [arc]) THEN REWRITE_TAC[path] THEN MATCH_MP_TAC (REWRITE_RULE[IMP_CONJ_ALT] CONTINUOUS_ON_SUBSET) THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN REWRITE_TAC[SUBSET; IN_DELETE; GSYM DROP_EQ; IN_INTERVAL_1] THEN REAL_ARITH_TAC; MATCH_MP_TAC CONNECTED_INTERMEDIATE_CLOSURE THEN EXISTS_TAC `interval(vec 0:real^1,t)` THEN REWRITE_TAC[CONNECTED_INTERVAL; CLOSURE_INTERVAL] THEN REWRITE_TAC[INTERVAL_EQ_EMPTY_1] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[SUBSET; IN_DELETE; GSYM DROP_EQ; IN_INTERVAL_1] THEN REWRITE_TAC[NOT_IN_EMPTY] THEN ASM_REAL_ARITH_TAC]; REWRITE_TAC[SET_RULE `~(IMAGE f s INTER t = {}) <=> ?x. x IN s /\ f x IN t`] THEN EXISTS_TAC `vec 0:real^1` THEN REWRITE_TAC[IN_INTERVAL_1; IN_DELETE; REAL_LE_REFL] THEN RULE_ASSUM_TAC(REWRITE_RULE[IN_INTERVAL_1]) THEN ASM SET_TAC[pathstart]; REWRITE_TAC[SET_RULE `IMAGE g i INTER s = {} <=> !x. x IN i ==> ~(g x IN s)`] THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IN_DELETE; IN_UNIV; IN_DIFF] THEN X_GEN_TAC `z:real^1` THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[GSYM DROP_EQ; IN_INTERVAL_1] THEN DISCH_TAC THEN DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC) THEN ASM_REWRITE_TAC[GSYM REAL_LE_ANTISYM] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[IN_INTERVAL_1] THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [IN_INTERVAL_1]) THEN ASM_REAL_ARITH_TAC]]);;
let DENSE_ACCESSIBLE_FRONTIER_POINTS_CONNECTED = 
prove (`!s:real^N->bool v x. open s /\ connected s /\ x IN s /\ open_in (subtopology euclidean (frontier s)) v /\ ~(v = {}) ==> ?g. arc g /\ IMAGE g (interval [vec 0,vec 1] DELETE vec 1) SUBSET s /\ pathstart g = x /\ pathfinish g IN v`,
REPEAT STRIP_TAC THEN MP_TAC(ISPECL [`s:real^N->bool`; `v:real^N->bool`] DENSE_ACCESSIBLE_FRONTIER_POINTS) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `g:real^1->real^N` STRIP_ASSUME_TAC) THEN SUBGOAL_THEN `path_connected(s:real^N->bool)` MP_TAC THENL [ASM_MESON_TAC[CONNECTED_OPEN_PATH_CONNECTED]; ALL_TAC] THEN REWRITE_TAC[PATH_CONNECTED_IFF_PATH_COMPONENT] THEN DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `pathstart g:real^N`]) THEN ASM_REWRITE_TAC[path_component; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `f:real^1->real^N` THEN STRIP_TAC THEN MP_TAC(ISPECL [`f ++ g:real^1->real^N`; `x:real^N`; `pathfinish g:real^N`] PATH_CONTAINS_ARC) THEN ASM_SIMP_TAC[PATH_JOIN_EQ; ARC_IMP_PATH; PATH_IMAGE_JOIN; PATHSTART_JOIN; PATHFINISH_JOIN] THEN FIRST_ASSUM(MP_TAC o MATCH_MP OPEN_IN_IMP_SUBSET) THEN GEN_REWRITE_TAC LAND_CONV [SUBSET] THEN ASM_SIMP_TAC[frontier; INTERIOR_OPEN; IN_DIFF] THEN DISCH_TAC THEN ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `h:real^1->real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(SET_RULE `a IN s /\ IMAGE f s DELETE (f a) SUBSET t /\ (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) ==> IMAGE f (s DELETE a) SUBSET t`) THEN REWRITE_TAC[ENDS_IN_UNIT_INTERVAL] THEN CONJ_TAC THENL [REWRITE_TAC[GSYM path_image]; ASM_MESON_TAC[arc]] THEN FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `h SUBSET f UNION g ==> f SUBSET s /\ g DELETE a SUBSET s ==> h DELETE a SUBSET s`)) THEN ASM_REWRITE_TAC[] THEN RULE_ASSUM_TAC(REWRITE_RULE[path_image; pathstart; pathfinish]) THEN REWRITE_TAC[path_image] THEN ASM SET_TAC[]);;
let DENSE_ACCESSIBLE_FRONTIER_POINT_PAIRS = 
prove (`!s u v:real^N->bool. open s /\ connected s /\ open_in (subtopology euclidean (frontier s)) u /\ open_in (subtopology euclidean (frontier s)) v /\ ~(u = {}) /\ ~(v = {}) /\ ~(u = v) ==> ?g. arc g /\ pathstart g IN u /\ pathfinish g IN v /\ IMAGE g (interval(vec 0,vec 1)) SUBSET s`,
GEN_TAC THEN REWRITE_TAC[CONJ_ASSOC] THEN ONCE_REWRITE_TAC[IMP_CONJ_ALT] THEN GEN_REWRITE_TAC (funpow 2 BINDER_CONV o LAND_CONV o RAND_CONV) [GSYM SUBSET_ANTISYM_EQ] THEN REWRITE_TAC[DE_MORGAN_THM; GSYM CONJ_ASSOC] THEN MATCH_MP_TAC(MESON[] `(!u v. R u v ==> R v u) /\ (!u v. P u v ==> R u v) ==> !u v. P u v \/ P v u ==> R u v`) THEN CONJ_TAC THENL [REPEAT GEN_TAC THEN DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `g:real^1->real^N` THEN STRIP_TAC THEN EXISTS_TAC `reversepath g:real^1->real^N` THEN ASM_SIMP_TAC[ARC_REVERSEPATH; PATHSTART_REVERSEPATH; PATHFINISH_REVERSEPATH] THEN REWRITE_TAC[reversepath] THEN ONCE_REWRITE_TAC[GSYM o_DEF] THEN REWRITE_TAC[IMAGE_o] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `IMAGE f i SUBSET t ==> IMAGE r i SUBSET i ==> IMAGE f (IMAGE r i) SUBSET t`)) THEN SIMP_TAC[SUBSET; FORALL_IN_IMAGE; IN_INTERVAL_1; DROP_SUB; DROP_VEC] THEN REAL_ARITH_TAC; ALL_TAC] THEN REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[FRONTIER_EMPTY; OPEN_IN_SUBTOPOLOGY_EMPTY] THENL [CONV_TAC TAUT; STRIP_TAC THEN UNDISCH_TAC `~(s:real^N->bool = {})`] THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN MP_TAC(ISPECL [`s:real^N->bool`; `v:real^N->bool`; `x:real^N`] DENSE_ACCESSIBLE_FRONTIER_POINTS_CONNECTED) THEN ASM_REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `g:real^1->real^N` THEN STRIP_TAC THEN MP_TAC(ISPECL [`s:real^N->bool`; `(u DELETE pathfinish g):real^N->bool`; `x:real^N`] DENSE_ACCESSIBLE_FRONTIER_POINTS_CONNECTED) THEN ASM_SIMP_TAC[OPEN_IN_DELETE; IN_DELETE; LEFT_IMP_EXISTS_THM] THEN ANTS_TAC THENL [ASM SET_TAC[]; REWRITE_TAC[LEFT_IMP_EXISTS_THM]] THEN X_GEN_TAC `h:real^1->real^N` THEN STRIP_TAC THEN MP_TAC(ISPECL [`(reversepath h ++ g):real^1->real^N`; `pathfinish h:real^N`; `pathfinish g:real^N`] PATH_CONTAINS_ARC) THEN ASM_SIMP_TAC[PATH_JOIN; PATHSTART_JOIN; PATHFINISH_JOIN; PATHSTART_REVERSEPATH; PATHFINISH_REVERSEPATH; PATH_REVERSEPATH; ARC_IMP_PATH; PATH_IMAGE_JOIN; PATH_IMAGE_REVERSEPATH] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `q:real^1->real^N` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[OPEN_CLOSED_INTERVAL_1] THEN MATCH_MP_TAC(SET_RULE `(!x y. x IN s /\ y IN s /\ f x = f y ==> x = y) /\ t SUBSET s /\ IMAGE f s SUBSET u UNION IMAGE f t ==> IMAGE f (s DIFF t) SUBSET u`) THEN REWRITE_TAC[INSERT_SUBSET; EMPTY_SUBSET; ENDS_IN_UNIT_INTERVAL] THEN CONJ_TAC THENL [ASM_MESON_TAC[arc]; REWRITE_TAC[GSYM path_image]] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (REWRITE_RULE[IMP_CONJ] SUBSET_TRANS)) THEN RULE_ASSUM_TAC(REWRITE_RULE[pathstart; pathfinish; path_image]) THEN REWRITE_TAC[path_image] THEN ASM SET_TAC[]);;
(* ------------------------------------------------------------------------- *) (* Some simple positive connection theorems. *) (* ------------------------------------------------------------------------- *)
let PATH_CONNECTED_CONVEX_DIFF_CARD_LT = 
prove (`!u s:real^N->bool. convex u /\ ~(collinear u) /\ s <_c (:real) ==> path_connected(u DIFF s)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[path_connected; IN_DIFF; IN_UNIV] THEN MAP_EVERY X_GEN_TAC [`a:real^N`; `b:real^N`] THEN STRIP_TAC THEN ASM_CASES_TAC `a:real^N = b` THENL [EXISTS_TAC `linepath(a:real^N,b)` THEN REWRITE_TAC[PATHSTART_LINEPATH; PATHFINISH_LINEPATH; PATH_LINEPATH] THEN ASM_REWRITE_TAC[PATH_IMAGE_LINEPATH; SEGMENT_REFL] THEN ASM SET_TAC[]; ALL_TAC] THEN ABBREV_TAC `m:real^N = midpoint(a,b)` THEN SUBGOAL_THEN `~(m:real^N = a) /\ ~(m = b)` STRIP_ASSUME_TAC THENL [ASM_MESON_TAC[MIDPOINT_EQ_ENDPOINT]; ALL_TAC] THEN POP_ASSUM_LIST(MP_TAC o end_itlist CONJ o rev) THEN GEOM_ORIGIN_TAC `m:real^N` THEN REPEAT GEN_TAC THEN GEOM_NORMALIZE_TAC `b:real^N` THEN REWRITE_TAC[] THEN GEN_TAC THEN GEOM_BASIS_MULTIPLE_TAC 1 `b:real^N` THEN X_GEN_TAC `bbb:real` THEN DISCH_TAC THEN SIMP_TAC[NORM_MUL; NORM_BASIS; DIMINDEX_GE_1; LE_REFL] THEN ASM_REWRITE_TAC[real_abs; REAL_MUL_RID] THEN DISCH_THEN SUBST1_TAC THEN POP_ASSUM(K ALL_TAC) THEN REPEAT GEN_TAC THEN REWRITE_TAC[midpoint; VECTOR_MUL_LID] THEN REWRITE_TAC[VECTOR_ARITH `inv(&2) % (a + b):real^N = vec 0 <=> a = --b`] THEN ASM_CASES_TAC `a:real^N = --(basis 1)` THEN ASM_REWRITE_TAC[] THEN POP_ASSUM(K ALL_TAC) THEN REPLICATE_TAC 7 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN DISCH_THEN(K ALL_TAC) THEN SUBGOAL_THEN `segment[--basis 1:real^N,basis 1] SUBSET u` ASSUME_TAC THENL [REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC HULL_MINIMAL THEN ASM SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `(vec 0:real^N) IN u` ASSUME_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o GEN_REWRITE_RULE I [SUBSET]) THEN REWRITE_TAC[IN_SEGMENT] THEN EXISTS_TAC `&1 / &2` THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN VECTOR_ARITH_TAC; ALL_TAC] THEN SUBGOAL_THEN `?c:real^N k. 1 <= k /\ ~(k = 1) /\ k <= dimindex(:N) /\ c IN u /\ ~(c$k = &0)` STRIP_ASSUME_TAC THENL [REWRITE_TAC[GSYM NOT_FORALL_THM; TAUT `a /\ ~b /\ c /\ d /\ ~e <=> ~(d ==> a /\ c ==> ~b ==> e)`] THEN DISCH_TAC THEN UNDISCH_TAC `~collinear(u:real^N->bool)` THEN REWRITE_TAC[COLLINEAR_AFFINE_HULL] THEN MAP_EVERY EXISTS_TAC [`vec 0:real^N`; `basis 1:real^N`] THEN SIMP_TAC[AFFINE_HULL_EQ_SPAN; HULL_INC; IN_INSERT; SPAN_INSERT_0] THEN REWRITE_TAC[SPAN_SING; SUBSET; IN_ELIM_THM; IN_UNIV] THEN X_GEN_TAC `c:real^N` THEN DISCH_TAC THEN EXISTS_TAC `(c:real^N)$1` THEN SIMP_TAC[CART_EQ; VECTOR_MUL_COMPONENT; BASIS_COMPONENT] THEN REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_MUL_RID; REAL_MUL_RZERO] THEN ASM_MESON_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `~(c:real^N = vec 0)` ASSUME_TAC THENL [ASM_SIMP_TAC[CART_EQ; VEC_COMPONENT] THEN ASM_MESON_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `segment[vec 0:real^N,c] SUBSET u` ASSUME_TAC THENL [REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC HULL_MINIMAL THEN ASM SET_TAC[]; ALL_TAC] THEN SUBGOAL_THEN `?z:real^N. z IN segment[vec 0,c] /\ (segment[--basis 1,z] UNION segment[z,basis 1]) INTER s = {}` STRIP_ASSUME_TAC THENL [ALL_TAC; EXISTS_TAC `linepath(--basis 1:real^N,z) ++ linepath(z,basis 1)` THEN ASM_SIMP_TAC[PATH_JOIN; PATHSTART_JOIN; PATHFINISH_JOIN; PATH_LINEPATH; PATHSTART_LINEPATH; PATHFINISH_LINEPATH; PATH_IMAGE_JOIN] THEN REWRITE_TAC[PATH_IMAGE_LINEPATH] THEN FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `(t UNION v) INTER s = {} ==> t SUBSET u /\ v SUBSET u ==> (t UNION v) SUBSET u DIFF s`)) THEN REWRITE_TAC[SEGMENT_CONVEX_HULL] THEN CONJ_TAC THEN MATCH_MP_TAC HULL_MINIMAL THEN ASM SET_TAC[]] THEN MATCH_MP_TAC(SET_RULE `~(s SUBSET {z | z IN s /\ ~P z}) ==> ?z. z IN s /\ P z`) THEN DISCH_THEN(MP_TAC o MATCH_MP CARD_LE_SUBSET) THEN REWRITE_TAC[CARD_NOT_LE; SET_RULE `~((b UNION c) INTER s = {}) <=> ~(b INTER s = {}) \/ ~(c INTER s = {})`] THEN REWRITE_TAC[SET_RULE `{x | P x /\ (Q x \/ R x)} = {x | P x /\ Q x} UNION {x | P x /\ R x}`] THEN W(MP_TAC o PART_MATCH lhand UNION_LE_ADD_C o lhand o snd) THEN MATCH_MP_TAC(ONCE_REWRITE_RULE[IMP_CONJ_ALT] CARD_LET_TRANS) THEN TRANS_TAC CARD_LTE_TRANS `(:real)` THEN CONJ_TAC THENL [MATCH_MP_TAC CARD_ADD2_ABSORB_LT THEN REWRITE_TAC[real_INFINITE]; MATCH_MP_TAC CARD_EQ_IMP_LE THEN ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN ASM_SIMP_TAC[CARD_EQ_SEGMENT]] THEN REWRITE_TAC[MESON[SEGMENT_SYM] `segment[--a:real^N,b] = segment[b,--a]`] THEN SUBGOAL_THEN `!b:real^N. b IN u /\ ~(b IN s) /\ ~(b = vec 0) /\ b$k = &0 ==> {z | z IN segment[vec 0,c] /\ ~(segment[z,b] INTER s = {})} <_c (:real)` (fun th -> CONJ_TAC THEN MATCH_MP_TAC th THEN REWRITE_TAC[VECTOR_NEG_EQ_0; VECTOR_NEG_COMPONENT] THEN ASM_SIMP_TAC[BASIS_NONZERO; DIMINDEX_GE_1; LE_REFL; BASIS_COMPONENT] THEN REWRITE_TAC[REAL_NEG_0]) THEN REPEAT STRIP_TAC THEN TRANS_TAC CARD_LET_TRANS `s:real^N->bool` THEN ASM_REWRITE_TAC[] THEN REWRITE_TAC[GSYM MEMBER_NOT_EMPTY; IN_INTER; RIGHT_AND_EXISTS_THM] THEN ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> r /\ p /\ q`] THEN MATCH_MP_TAC CARD_LE_RELATIONAL THEN MAP_EVERY X_GEN_TAC [`w:real^N`; `x1:real^N`; `x2:real^N`] THEN REWRITE_TAC[SEGMENT_SYM] THEN STRIP_TAC THEN ASM_CASES_TAC `x2:real^N = x1` THEN ASM_REWRITE_TAC[] THEN MP_TAC(ISPECL [`x1:real^N`; `b:real^N`; `x2:real^N`] INTER_SEGMENT) THEN REWRITE_TAC[NOT_IMP; SEGMENT_SYM] THEN CONJ_TAC THENL [DISJ2_TAC; REWRITE_TAC[SEGMENT_SYM] THEN ASM SET_TAC[]] THEN ONCE_REWRITE_TAC[SET_RULE `{x1,b,x2} = {x1,x2,b}`] THEN ASM_SIMP_TAC[COLLINEAR_3_AFFINE_HULL] THEN STRIP_TAC THEN SUBGOAL_THEN `(b:real^N) IN affine hull {vec 0,c}` MP_TAC THENL [FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE `b IN s ==> s SUBSET t ==> b IN t`)) THEN MATCH_MP_TAC HULL_MINIMAL THEN REWRITE_TAC[AFFINE_AFFINE_HULL] THEN MATCH_MP_TAC SUBSET_TRANS THEN EXISTS_TAC `segment[c:real^N,vec 0]` THEN CONJ_TAC THENL [ASM SET_TAC[]; ONCE_REWRITE_TAC[SEGMENT_SYM]] THEN REWRITE_TAC[SEGMENT_CONVEX_HULL; CONVEX_HULL_SUBSET_AFFINE_HULL]; REWRITE_TAC[AFFINE_HULL_2_ALT; IN_ELIM_THM; IN_UNIV] THEN REWRITE_TAC[VECTOR_ADD_LID; VECTOR_SUB_RZERO; NOT_EXISTS_THM] THEN X_GEN_TAC `r:real` THEN ASM_CASES_TAC `r = &0` THEN ASM_REWRITE_TAC[VECTOR_MUL_LZERO] THEN CONV_TAC(RAND_CONV SYM_CONV) THEN DISCH_THEN(MP_TAC o AP_TERM `\x:real^N. x$k`) THEN ASM_SIMP_TAC[VECTOR_MUL_COMPONENT; REAL_ENTIRE]]);;
let PATH_CONNECTED_COMPLEMENT_CARD_LT = 
prove (`!s. 2 <= dimindex(:N) /\ s <_c (:real) ==> path_connected((:real^N) DIFF s)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_CONVEX_DIFF_CARD_LT THEN ASM_REWRITE_TAC[CONVEX_UNIV; COLLINEAR_AFF_DIM; AFF_DIM_UNIV] THEN REWRITE_TAC[INT_OF_NUM_LE] THEN ASM_ARITH_TAC);;
let PATH_CONNECTED_OPEN_IN_DIFF_CARD_LT = 
prove (`!s t:real^N->bool. connected s /\ open_in (subtopology euclidean (affine hull s)) s /\ ~collinear s /\ t <_c (:real) ==> path_connected(s DIFF t)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[PATH_CONNECTED_IFF_PATH_COMPONENT; IN_DIFF] THEN REWRITE_TAC[TAUT `(p /\ q) /\ (r /\ s) <=> p /\ r /\ q /\ s`] THEN MATCH_MP_TAC CONNECTED_EQUIVALENCE_RELATION_GEN THEN ASM_REWRITE_TAC[IN_DIFF] THEN REWRITE_TAC[PATH_COMPONENT_SYM; PATH_COMPONENT_TRANS] THEN CONJ_TAC THENL [MAP_EVERY X_GEN_TAC [`u:real^N->bool`; `x:real^N`] THEN STRIP_TAC THEN SUBGOAL_THEN `open_in (subtopology euclidean (affine hull s)) (u:real^N->bool)` MP_TAC THENL [ASM_MESON_TAC[OPEN_IN_TRANS]; ALL_TAC] THEN REWRITE_TAC[OPEN_IN_CONTAINS_BALL] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `x:real^N`)) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN MATCH_MP_TAC(SET_RULE `~(s SUBSET t) ==> ?x. x IN s /\ ~(x IN t)`) THEN DISCH_THEN(MP_TAC o MATCH_MP CARD_LE_SUBSET) THEN REWRITE_TAC[CARD_NOT_LE] THEN TRANS_TAC CARD_LTE_TRANS `(:real)` THEN ASM_REWRITE_TAC[] THEN TRANS_TAC CARD_LE_TRANS `ball(x:real^N,r) INTER affine hull s` THEN ASM_SIMP_TAC[CARD_LE_SUBSET] THEN MATCH_MP_TAC CARD_EQ_IMP_LE THEN ONCE_REWRITE_TAC[CARD_EQ_SYM] THEN MATCH_MP_TAC CARD_EQ_CONVEX THEN EXISTS_TAC `x:real^N` THEN ASM_SIMP_TAC[CONVEX_INTER; AFFINE_IMP_CONVEX; CONVEX_BALL; AFFINE_AFFINE_HULL; IN_INTER; CENTRE_IN_BALL; HULL_INC] THEN SUBGOAL_THEN `~(s SUBSET {x:real^N})` MP_TAC THENL [ASM_MESON_TAC[COLLINEAR_SUBSET; COLLINEAR_SING]; ALL_TAC] THEN REWRITE_TAC[SUBSET; IN_SING; NOT_FORALL_THM; NOT_IMP] THEN DISCH_THEN(X_CHOOSE_THEN `y:real^N` STRIP_ASSUME_TAC) THEN EXISTS_TAC `x + r / &2 / norm(y - x) % (y - x):real^N` THEN RULE_ASSUM_TAC(REWRITE_RULE[SUBSET]) THEN ASM_SIMP_TAC[HULL_INC; IN_AFFINE_ADD_MUL_DIFF; AFFINE_AFFINE_HULL] THEN REWRITE_TAC[IN_BALL; VECTOR_ARITH `x:real^N = x + y <=> y = vec 0`] THEN ASM_SIMP_TAC[VECTOR_MUL_EQ_0; REAL_DIV_EQ_0; NORM_EQ_0; VECTOR_SUB_EQ; REAL_LT_IMP_NZ; NORM_ARITH `dist(x:real^N,x + y) = norm y`] THEN REWRITE_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NUM; REAL_ABS_NORM] THEN ASM_SIMP_TAC[REAL_DIV_RMUL; NORM_EQ_0; VECTOR_SUB_EQ] THEN ASM_REAL_ARITH_TAC; X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [OPEN_IN_CONTAINS_BALL]) THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `x:real^N`)) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `r:real` STRIP_ASSUME_TAC) THEN EXISTS_TAC `ball(x:real^N,r) INTER affine hull s` THEN ASM_SIMP_TAC[IN_INTER; HULL_INC; CENTRE_IN_BALL] THEN CONJ_TAC THENL [MATCH_MP_TAC OPEN_IN_SUBSET_TRANS THEN EXISTS_TAC `affine hull s:real^N->bool` THEN ASM_SIMP_TAC[ONCE_REWRITE_RULE[INTER_COMM]OPEN_IN_OPEN_INTER; OPEN_BALL]; MAP_EVERY X_GEN_TAC [`y:real^N`; `z:real^N`] THEN STRIP_TAC THEN MP_TAC(ISPECL [`ball(x:real^N,r) INTER affine hull s`; `t:real^N->bool`] PATH_CONNECTED_CONVEX_DIFF_CARD_LT) THEN ASM_SIMP_TAC[CONVEX_INTER; AFFINE_IMP_CONVEX; CONVEX_BALL; AFFINE_AFFINE_HULL] THEN ANTS_TAC THENL [REWRITE_TAC[COLLINEAR_AFF_DIM] THEN ONCE_REWRITE_TAC[INTER_COMM] THEN W(MP_TAC o PART_MATCH (lhs o rand) AFF_DIM_CONVEX_INTER_OPEN o lhand o rand o snd) THEN SIMP_TAC[AFFINE_IMP_CONVEX; AFFINE_AFFINE_HULL; OPEN_BALL] THEN ANTS_TAC THENL [ASM SET_TAC[CENTRE_IN_BALL]; ALL_TAC] THEN DISCH_THEN SUBST1_TAC THEN REWRITE_TAC[AFF_DIM_AFFINE_HULL] THEN ASM_REWRITE_TAC[GSYM COLLINEAR_AFF_DIM]; REWRITE_TAC[PATH_CONNECTED_IFF_PATH_COMPONENT] THEN DISCH_THEN(MP_TAC o SPECL [`y:real^N`; `z:real^N`]) THEN ASM_REWRITE_TAC[IN_INTER; IN_DIFF] THEN MATCH_MP_TAC(REWRITE_RULE[IMP_CONJ] PATH_COMPONENT_OF_SUBSET) THEN ASM SET_TAC[]]]]);;
let CONNECTED_OPEN_IN_DIFF_CARD_LT = 
prove (`!s t:real^N->bool. connected s /\ open_in (subtopology euclidean (affine hull s)) s /\ ~collinear s /\ t <_c (:real) ==> connected(s DIFF t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_IMP_CONNECTED THEN MATCH_MP_TAC PATH_CONNECTED_OPEN_IN_DIFF_CARD_LT THEN ASM_REWRITE_TAC[]);;
let PATH_CONNECTED_OPEN_DIFF_CARD_LT = 
prove (`!s t:real^N->bool. 2 <= dimindex(:N) /\ open s /\ connected s /\ t <_c (:real) ==> path_connected(s DIFF t)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `s:real^N->bool = {}` THEN ASM_REWRITE_TAC[EMPTY_DIFF; PATH_CONNECTED_EMPTY] THEN MATCH_MP_TAC PATH_CONNECTED_OPEN_IN_DIFF_CARD_LT THEN ASM_REWRITE_TAC[COLLINEAR_AFF_DIM] THEN ASM_SIMP_TAC[AFFINE_HULL_OPEN; AFF_DIM_OPEN] THEN ASM_REWRITE_TAC[INT_OF_NUM_LE; SUBTOPOLOGY_UNIV; GSYM OPEN_IN] THEN ASM_ARITH_TAC);;
let CONNECTED_OPEN_DIFF_CARD_LT = 
prove (`!s t:real^N->bool. 2 <= dimindex(:N) /\ open s /\ connected s /\ t <_c (:real) ==> connected(s DIFF t)`,
let PATH_CONNECTED_OPEN_DIFF_COUNTABLE = 
prove (`!s t:real^N->bool. 2 <= dimindex(:N) /\ open s /\ connected s /\ COUNTABLE t ==> path_connected(s DIFF t)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_OPEN_DIFF_CARD_LT THEN ASM_REWRITE_TAC[GSYM CARD_NOT_LE] THEN ASM_MESON_TAC[UNCOUNTABLE_REAL; CARD_LE_COUNTABLE]);;
let CONNECTED_OPEN_DIFF_COUNTABLE = 
prove (`!s t:real^N->bool. 2 <= dimindex(:N) /\ open s /\ connected s /\ COUNTABLE t ==> connected(s DIFF t)`,
let PATH_CONNECTED_OPEN_DELETE = 
prove (`!s a:real^N. 2 <= dimindex(:N) /\ open s /\ connected s ==> path_connected(s DELETE a)`,
REPEAT STRIP_TAC THEN REWRITE_TAC[SET_RULE `s DELETE a = s DIFF {a}`] THEN MATCH_MP_TAC PATH_CONNECTED_OPEN_DIFF_COUNTABLE THEN ASM_REWRITE_TAC[COUNTABLE_SING]);;
let CONNECTED_OPEN_DELETE = 
prove (`!s a:real^N. 2 <= dimindex(:N) /\ open s /\ connected s ==> connected(s DELETE a)`,
let PATH_CONNECTED_PUNCTURED_UNIVERSE = 
prove (`!a. 2 <= dimindex(:N) ==> path_connected((:real^N) DIFF {a})`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC PATH_CONNECTED_OPEN_DIFF_COUNTABLE THEN ASM_REWRITE_TAC[OPEN_UNIV; CONNECTED_UNIV; COUNTABLE_SING]);;
let CONNECTED_PUNCTURED_UNIVERSE = 
prove (`!a. 2 <= dimindex(:N) ==> connected((:real^N) DIFF {a})`,
let PATH_CONNECTED_PUNCTURED_BALL = 
prove (`!a:real^N r. 2 <= dimindex(:N) ==> path_connected(ball(a,r) DELETE a)`,
let CONNECTED_PUNCTURED_BALL = 
prove (`!a:real^N r. 2 <= dimindex(:N) ==> connected(ball(a,r) DELETE a)`,
let PATH_CONNECTED_SPHERE = 
prove (`!a:real^N r. 2 <= dimindex(:N) ==> path_connected(sphere(a,r))`,
REPEAT GEN_TAC THEN REWRITE_TAC[sphere; dist] THEN ONCE_REWRITE_TAC[NORM_SUB] THEN GEOM_ORIGIN_TAC `a:real^N` THEN GEN_TAC THEN REWRITE_TAC[VECTOR_SUB_RZERO] THEN DISCH_TAC THEN REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC (REAL_ARITH `r < &0 \/ r = &0 \/ &0 < r`) THENL [ASM_SIMP_TAC[NORM_ARITH `r < &0 ==> ~(norm(x:real^N) = r)`] THEN REWRITE_TAC[EMPTY_GSPEC; PATH_CONNECTED_EMPTY]; ASM_REWRITE_TAC[NORM_EQ_0; SING_GSPEC; PATH_CONNECTED_SING]; SUBGOAL_THEN `{x:real^N | norm x = r} = IMAGE (\x. r / norm x % x) ((:real^N) DIFF {vec 0})` SUBST1_TAC THENL [MATCH_MP_TAC SUBSET_ANTISYM THEN REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN REWRITE_TAC[IN_IMAGE; IN_ELIM_THM; IN_DIFF; IN_SING; IN_UNIV] THEN ASM_SIMP_TAC[NORM_MUL; REAL_ABS_DIV; REAL_ABS_NORM; REAL_DIV_RMUL; NORM_EQ_0; REAL_ARITH `&0 < r ==> abs r = r`] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN EXISTS_TAC `x:real^N` THEN ASM_SIMP_TAC[REAL_DIV_REFL; REAL_LT_IMP_NZ; VECTOR_MUL_LID] THEN ASM_MESON_TAC[NORM_0; REAL_LT_IMP_NZ]; MATCH_MP_TAC PATH_CONNECTED_CONTINUOUS_IMAGE THEN ASM_SIMP_TAC[PATH_CONNECTED_PUNCTURED_UNIVERSE] THEN MATCH_MP_TAC CONTINUOUS_ON_MUL THEN REWRITE_TAC[CONTINUOUS_ON_ID] THEN REWRITE_TAC[o_DEF; CONTINUOUS_ON_EQ_CONTINUOUS_WITHIN] THEN X_GEN_TAC `x:real^N` THEN REWRITE_TAC[IN_DIFF; IN_UNIV; IN_SING] THEN DISCH_TAC THEN REWRITE_TAC[real_div; LIFT_CMUL] THEN MATCH_MP_TAC CONTINUOUS_CMUL THEN MATCH_MP_TAC(REWRITE_RULE[o_DEF] CONTINUOUS_AT_WITHIN_INV) THEN ASM_REWRITE_TAC[NORM_EQ_0] THEN MATCH_MP_TAC CONTINUOUS_AT_WITHIN THEN REWRITE_TAC[REWRITE_RULE[o_DEF] CONTINUOUS_AT_LIFT_NORM]]]);;
let CONNECTED_SPHERE = 
prove (`!a:real^N r. 2 <= dimindex(:N) ==> connected(sphere(a,r))`,
let CONNECTED_SPHERE_EQ = 
prove (`!a:real^N r. connected(sphere(a,r)) <=> 2 <= dimindex(:N) \/ r <= &0`,
let lemma = prove
   (`!a:real^1 r. &0 < r
         ==> ?x y. ~(x = y) /\ dist(a,x) = r /\ dist(a,y) = r`,
    MP_TAC SPHERE_1 THEN REPEAT(MATCH_MP_TAC MONO_FORALL THEN GEN_TAC) THEN
    COND_CASES_TAC THENL [ASM_REAL_ARITH_TAC; ALL_TAC] THEN
    REWRITE_TAC[EXTENSION; IN_SPHERE; IN_INSERT; NOT_IN_EMPTY] THEN
    REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(MESON[]
    `~(a = b) ==> ?x y. ~(x = y) /\ (x = a \/ x = b) /\ (y = a \/ y = b)`) THEN
    REWRITE_TAC[VECTOR_ARITH `a - r:real^1 = a + r <=> r = vec 0`] THEN
    REWRITE_TAC[GSYM DROP_EQ; DROP_VEC; LIFT_DROP] THEN ASM_REAL_ARITH_TAC) in
  REPEAT GEN_TAC THEN ASM_CASES_TAC `r < &0` THEN
  ASM_SIMP_TAC[SPHERE_EMPTY; CONNECTED_EMPTY; REAL_LT_IMP_LE] THEN
  ASM_CASES_TAC `r = &0` THEN
  ASM_SIMP_TAC[SPHERE_SING; REAL_LE_REFL; CONNECTED_SING] THEN
  SUBGOAL_THEN `&0 < r` ASSUME_TAC THENL
   [ASM_REAL_ARITH_TAC; ASM_REWRITE_TAC[GSYM REAL_NOT_LT]] THEN
  EQ_TAC THEN SIMP_TAC[CONNECTED_SPHERE] THEN
  DISCH_THEN(MP_TAC o MATCH_MP CONNECTED_FINITE_IFF_SING) THEN
  ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
  SIMP_TAC[DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> (2 <= n <=> ~(n = 1))`] THEN
  GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM DIMINDEX_1] THEN
  DISCH_TAC THEN FIRST_ASSUM (fun th ->
    REWRITE_TAC[GEOM_EQUAL_DIMENSION_RULE th FINITE_SPHERE_1]) THEN
  REWRITE_TAC[SET_RULE
   `~(s = {} \/ ?a. s = {a}) <=> ?x y. ~(x = y) /\ x IN s /\ y IN s`] THEN
  REWRITE_TAC[IN_SPHERE] THEN
  FIRST_X_ASSUM(MATCH_MP_TAC o C GEOM_EQUAL_DIMENSION_RULE lemma) THEN
  ASM_REWRITE_TAC[]);;
let PATH_CONNECTED_SPHERE_EQ = 
prove (`!a:real^N r. path_connected(sphere(a,r)) <=> 2 <= dimindex(:N) \/ r <= &0`,
REPEAT GEN_TAC THEN EQ_TAC THENL [REWRITE_TAC[GSYM CONNECTED_SPHERE_EQ; PATH_CONNECTED_IMP_CONNECTED]; STRIP_TAC THEN ASM_SIMP_TAC[PATH_CONNECTED_SPHERE]] THEN ASM_CASES_TAC `r < &0` THEN ASM_SIMP_TAC[SPHERE_EMPTY; PATH_CONNECTED_EMPTY] THEN ASM_CASES_TAC `r = &0` THEN ASM_SIMP_TAC[SPHERE_SING; PATH_CONNECTED_SING] THEN ASM_REAL_ARITH_TAC);;
let FINITE_SPHERE = 
prove (`!a:real^N r. FINITE(sphere(a,r)) <=> r <= &0 \/ dimindex(:N) = 1`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `dimindex(:N) = 1` THEN ASM_REWRITE_TAC[] THENL [RULE_ASSUM_TAC(REWRITE_RULE[GSYM DIMINDEX_1]) THEN FIRST_ASSUM(MATCH_ACCEPT_TAC o C PROVE_HYP (GEOM_EQUAL_DIMENSION_RULE(ASSUME `dimindex(:N) = dimindex(:1)`) FINITE_SPHERE_1)); ASM_SIMP_TAC[CONNECTED_SPHERE; ARITH_RULE `2 <= n <=> 1 <= n /\ ~(n = 1)`; DIMINDEX_GE_1; CONNECTED_FINITE_IFF_SING] THEN REWRITE_TAC[SET_RULE `(s = {} \/ ?a. s = {a}) <=> (!a b. a IN s /\ b IN s ==> a = b)`] THEN SIMP_TAC[IN_SPHERE] THEN EQ_TAC THENL [ALL_TAC; CONV_TAC NORM_ARITH] THEN ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN REWRITE_TAC[REAL_NOT_LE] THEN DISCH_TAC THEN MP_TAC(ISPECL [`a:real^N`; `r:real`] VECTOR_CHOOSE_DIST) THEN ASM_SIMP_TAC[REAL_LT_IMP_LE; LEFT_IMP_EXISTS_THM] THEN X_GEN_TAC `x:real^N` THEN DISCH_TAC THEN DISCH_THEN(MP_TAC o SPECL [`x:real^N`; `a - (x - a):real^N`]) THEN FIRST_X_ASSUM(K ALL_TAC o check (is_neg o concl)) THEN REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC NORM_ARITH]);;
let LIMIT_POINT_OF_SPHERE = 
prove (`!a r x:real^N. x limit_point_of sphere(a,r) <=> &0 < r /\ 2 <= dimindex(:N) /\ x IN sphere(a,r)`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `FINITE(sphere(a:real^N,r))` THENL [ASM_SIMP_TAC[LIMIT_POINT_FINITE]; ALL_TAC] THEN FIRST_ASSUM(MP_TAC o REWRITE_RULE[FINITE_SPHERE]) THEN REWRITE_TAC[DE_MORGAN_THM] THEN STRIP_TAC THEN ASM_REWRITE_TAC[REAL_NOT_LE; ARITH; REAL_NOT_LT] THEN ASM_SIMP_TAC[GSYM REAL_NOT_LE; DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> (2 <= n <=> ~(n = 1))`] THEN EQ_TAC THEN REWRITE_TAC[REWRITE_RULE[CLOSED_LIMPT] CLOSED_SPHERE] THEN DISCH_TAC THEN MATCH_MP_TAC CONNECTED_IMP_PERFECT THEN ASM_SIMP_TAC[CONNECTED_SPHERE_EQ; DIMINDEX_GE_1; ARITH_RULE `1 <= n ==> (2 <= n <=> ~(n = 1))`] THEN ASM_MESON_TAC[FINITE_SING]);;
let CARD_EQ_SPHERE = 
prove (`!a:real^N r. 2 <= dimindex(:N) /\ &0 < r ==> sphere(a,r) =_c (:real)`,
SIMP_TAC[CONNECTED_CARD_EQ_IFF_NONTRIVIAL; CONNECTED_SPHERE] THEN REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP(REWRITE_RULE[IMP_CONJ_ALT] FINITE_SUBSET)) THEN ASM_REWRITE_TAC[FINITE_SING; FINITE_SPHERE; REAL_NOT_LE; DE_MORGAN_THM] THEN ASM_ARITH_TAC);;
let PATH_CONNECTED_ANNULUS = 
prove (`(!a:real^N r1 r2. 2 <= dimindex(:N) ==> path_connected {x | r1 < norm(x - a) /\ norm(x - a) < r2}) /\ (!a:real^N r1 r2. 2 <= dimindex(:N) ==> path_connected {x | r1 < norm(x - a) /\ norm(x - a) <= r2}) /\ (!a:real^N r1 r2. 2 <= dimindex(:N) ==> path_connected {x | r1 <= norm(x - a) /\ norm(x - a) < r2}) /\ (!a:real^N r1 r2. 2 <= dimindex(:N) ==> path_connected {x | r1 <= norm(x - a) /\ norm(x - a) < r2})`,
let lemma = prove
   (`!a:real^N P.
      2 <= dimindex(:N) /\ path_connected {lift r | &0 <= r /\ P r}
      ==> path_connected {x | P(norm(x - a))}`,
    REPEAT GEN_TAC THEN GEOM_ORIGIN_TAC `a:real^N` THEN
    REWRITE_TAC[VECTOR_SUB_RZERO] THEN REPEAT STRIP_TAC THEN
    SUBGOAL_THEN
     `{x:real^N | P(norm(x))} =
      IMAGE (\z. drop(fstcart z) % sndcart z)
            {pastecart x y | x IN {lift x | &0 <= x /\ P x} /\
                             y IN {y | norm y = &1}}`
    SUBST1_TAC THENL
     [REWRITE_TAC[EXTENSION; IN_IMAGE] THEN ONCE_REWRITE_TAC[CONJ_SYM] THEN
      REWRITE_TAC[EXISTS_IN_GSPEC; FSTCART_PASTECART; SNDCART_PASTECART] THEN
      X_GEN_TAC `z:real^N` THEN REWRITE_TAC[EXISTS_LIFT; LIFT_DROP] THEN
      ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
      REWRITE_TAC[LIFT_IN_IMAGE_LIFT; IMAGE_ID] THEN
      REWRITE_TAC[IN_ELIM_THM] THEN
      EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[NORM_MUL; REAL_MUL_RID] THEN
      ASM_REWRITE_TAC[real_abs] THEN ASM_CASES_TAC `z:real^N = vec 0` THENL
       [MAP_EVERY EXISTS_TAC [`&0`; `basis 1:real^N`] THEN
        ASM_SIMP_TAC[NORM_BASIS; DIMINDEX_GE_1; LE_REFL; VECTOR_MUL_LZERO] THEN
        ASM_MESON_TAC[NORM_0; REAL_ABS_NUM; REAL_LE_REFL];
        MAP_EVERY EXISTS_TAC [`norm(z:real^N)`; `inv(norm z) % z:real^N`] THEN
        ASM_SIMP_TAC[REAL_ABS_NORM; NORM_MUL; VECTOR_MUL_ASSOC; VECTOR_MUL_LID;
          NORM_POS_LE; REAL_ABS_INV; REAL_MUL_RINV; REAL_MUL_LINV; NORM_EQ_0]];
      MATCH_MP_TAC PATH_CONNECTED_CONTINUOUS_IMAGE THEN CONJ_TAC THENL
       [MATCH_MP_TAC CONTINUOUS_ON_MUL THEN
        REWRITE_TAC[o_DEF; LIFT_DROP; ETA_AX] THEN
        SIMP_TAC[LINEAR_CONTINUOUS_ON; LINEAR_FSTCART; LINEAR_SNDCART];
        REWRITE_TAC[GSYM PCROSS] THEN
        MATCH_MP_TAC PATH_CONNECTED_PCROSS THEN ASM_REWRITE_TAC[] THEN
        ONCE_REWRITE_TAC[NORM_ARITH `norm y = norm(y - vec 0:real^N)`] THEN
        ONCE_REWRITE_TAC[NORM_SUB] THEN
        REWRITE_TAC[REWRITE_RULE[dist] (GSYM sphere)] THEN
        ASM_SIMP_TAC[PATH_CONNECTED_SPHERE]]]) in
  REPEAT STRIP_TAC THEN
  MP_TAC(ISPEC `a:real^N` lemma) THEN
  DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
  MATCH_MP_TAC CONVEX_IMP_PATH_CONNECTED THEN
  MATCH_MP_TAC IS_INTERVAL_CONVEX THEN
  REWRITE_TAC[is_interval] THEN
  ONCE_REWRITE_TAC[SIMPLE_IMAGE_GEN] THEN
  REWRITE_TAC[IN_IMAGE_LIFT_DROP; FORALL_1; DIMINDEX_1] THEN
  REWRITE_TAC[IN_ELIM_THM; GSYM drop] THEN REAL_ARITH_TAC);;
let CONNECTED_ANNULUS = 
prove (`(!a:real^N r1 r2. 2 <= dimindex(:N) ==> connected {x | r1 < norm(