(* ========================================================================= *)
(* Some special/counterintuive/weird topological spaces for counterexamples. *)
(* ========================================================================= *)

needs "Multivariate/metric.ml";;

(* ------------------------------------------------------------------------- *)
(* The indiscrete (trivial) topology.                                        *)
(* ------------------------------------------------------------------------- *)

let indiscrete_topology = new_definition
 `indiscrete_topology (u:A->bool) = topology {{},u}`;;

let OPEN_IN_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        open_in (indiscrete_topology u) s <=> s = {} \/ s = u`,
  REPEAT GEN_TAC THEN REWRITE_TAC[indiscrete_topology] THEN
  W(MP_TAC o fst o EQ_IMP_RULE o PART_MATCH (lhand o rand)
     (CONJUNCT2 topology_tybij) o rator o lhand o snd) THEN
  ANTS_TAC THENL
   [REWRITE_TAC[istopology; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
    REWRITE_TAC[FORALL_IN_INSERT; NOT_IN_EMPTY; FORALL_SUBSET_INSERT;
                UNIONS_INSERT; SUBSET_EMPTY; FORALL_UNWIND_THM2; UNIONS_0;
                UNION_EMPTY; INTER_EMPTY; INTER_IDEMPOT] THEN
    REWRITE_TAC[IN_INSERT];
    DISCH_THEN SUBST1_TAC THEN GEN_REWRITE_TAC LAND_CONV [GSYM IN] THEN
    REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY]]);;

let TOPSPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. topspace(indiscrete_topology u) = u`,
  REWRITE_TAC[topspace; OPEN_IN_INDISCRETE_TOPOLOGY] THEN SET_TAC[]);;

let CLOSED_IN_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        closed_in (indiscrete_topology u) s <=> s = {} \/ s = u`,
  REWRITE_TAC[closed_in; OPEN_IN_INDISCRETE_TOPOLOGY;
              TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  SET_TAC[]);;

let SUBTOPOLOGY_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        subtopology (indiscrete_topology u) s =
        indiscrete_topology (u INTER s)`,
  REPEAT GEN_TAC THEN REWRITE_TAC[TOPOLOGY_EQ] THEN
  GEN_TAC THEN REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_ALT] THEN
  REWRITE_TAC[OPEN_IN_INDISCRETE_TOPOLOGY] THEN
  ONCE_REWRITE_TAC[SET_RULE `x = a \/ x = b <=> x IN {a,b}`] THEN
  REWRITE_TAC[SIMPLE_IMAGE; IMAGE_CLAUSES; INTER_EMPTY] THEN
  REWRITE_TAC[INTER_COMM]);;

let COMPACT_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. compact_space (indiscrete_topology u)`,
  GEN_TAC THEN REWRITE_TAC[COMPACT_SPACE; OPEN_IN_INDISCRETE_TOPOLOGY] THEN
  X_GEN_TAC `U:(A->bool)->bool` THEN STRIP_TAC THEN
  EXISTS_TAC `U:(A->bool)->bool` THEN ASM_REWRITE_TAC[SUBSET_REFL] THEN
  MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `{{},(u:A->bool)}` THEN
  REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY] THEN
  GEN_REWRITE_TAC I [SUBSET] THEN ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY]);;

let COMPACT_IN_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        compact_in (indiscrete_topology u) s <=> s SUBSET u`,
  REWRITE_TAC[COMPACT_IN_SUBSPACE; TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[SUBTOPOLOGY_INDISCRETE_TOPOLOGY;
              COMPACT_SPACE_INDISCRETE_TOPOLOGY]);;

let LOCALLY_COMPACT_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. locally_compact_space (indiscrete_topology u)`,
  SIMP_TAC[COMPACT_IMP_LOCALLY_COMPACT_SPACE;
           COMPACT_SPACE_INDISCRETE_TOPOLOGY]);;

let COMPLETELY_REGULAR_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. completely_regular_space(indiscrete_topology u)`,
  REWRITE_TAC[completely_regular_space; CLOSED_IN_INDISCRETE_TOPOLOGY;
              TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[SET_RULE
    `(s = {} \/ s = u) /\ x IN u DIFF s <=> s = {} /\ x IN u`] THEN
  REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM; FORALL_UNWIND_THM2] THEN
  MAP_EVERY X_GEN_TAC [`u:A->bool`; `x:A`] THEN
  DISCH_TAC THEN EXISTS_TAC `(\x. &0):A->real` THEN
  REWRITE_TAC[CONTINUOUS_MAP_CONST; NOT_IN_EMPTY] THEN
  REWRITE_TAC[TOPSPACE_EUCLIDEANREAL_SUBTOPOLOGY;
               ENDS_IN_UNIT_REAL_INTERVAL]);;

let REGULAR_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. regular_space(indiscrete_topology u)`,
  SIMP_TAC[COMPLETELY_REGULAR_IMP_REGULAR_SPACE;
           COMPLETELY_REGULAR_SPACE_INDISCRETE_TOPOLOGY]);;

let T1_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. t1_space(indiscrete_topology u) <=> ?a. u SUBSET {a}`,
  REWRITE_TAC[T1_SPACE_CLOSED_IN_SING; TOPSPACE_INDISCRETE_TOPOLOGY;
              CLOSED_IN_INDISCRETE_TOPOLOGY] THEN
  SET_TAC[]);;

let T0_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. t0_space(indiscrete_topology u) <=> ?a. u SUBSET {a}`,
  GEN_TAC THEN REWRITE_TAC[t0_space; OPEN_IN_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_INDISCRETE_TOPOLOGY; RIGHT_OR_DISTRIB] THEN
  SIMP_TAC[EXISTS_OR_THM; UNWIND_THM2; NOT_IN_EMPTY] THEN SET_TAC[]);;

let HAUSDORFF_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. hausdorff_space(indiscrete_topology u) <=> ?a. u SUBSET {a}`,
  MESON_TAC[REGULAR_T1_EQ_HAUSDORFF_SPACE; REGULAR_SPACE_INDISCRETE_TOPOLOGY;
            T1_SPACE_INDISCRETE_TOPOLOGY]);;

let NORMAL_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. normal_space(indiscrete_topology u)`,
  GEN_TAC THEN REWRITE_TAC[normal_space; CLOSED_IN_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[OPEN_IN_INDISCRETE_TOPOLOGY; RIGHT_OR_DISTRIB] THEN
  REWRITE_TAC[EXISTS_OR_THM; GSYM CONJ_ASSOC; RIGHT_EXISTS_AND_THM] THEN
  REWRITE_TAC[UNWIND_THM2] THEN SET_TAC[]);;

let DERIVED_SET_OF_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        (indiscrete_topology u) derived_set_of s =
        if ?a. u INTER s SUBSET {a} then if DISJOINT u s then {} else u DIFF s
        else u`,
  REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[DERIVED_SET_OF_RESTRICT] THEN
  ONCE_REWRITE_TAC[DISJOINT; SET_RULE `u DIFF s = u DIFF (u INTER s)`] THEN
  MP_TAC(SET_RULE `(u INTER s:A->bool) SUBSET u`) THEN
  REWRITE_TAC[TOPSPACE_SUBTOPOLOGY; TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  SPEC_TAC(`u INTER s:A->bool`,`t:A->bool`) THEN X_GEN_TAC `s:A->bool` THEN
  STRIP_TAC THEN  ASM_CASES_TAC `s:A->bool = {}` THEN
  ASM_REWRITE_TAC[DERIVED_SET_OF_EMPTY; INTER_EMPTY; EMPTY_SUBSET] THEN
  REWRITE_TAC[derived_set_of; EXTENSION; IN_ELIM_THM; IN_INTER] THEN
  REWRITE_TAC[OPEN_IN_INDISCRETE_TOPOLOGY; TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TAUT
    `p /\ (q \/ r) ==> s <=> (q ==> p ==> s) /\ (r ==> p ==> s)`] THEN
  SIMP_TAC[NOT_IN_EMPTY; FORALL_UNWIND_THM2] THEN
  X_GEN_TAC `x:A` THEN COND_CASES_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
  ASM_CASES_TAC `(x:A) IN u` THEN ASM_REWRITE_TAC[NOT_IN_EMPTY; IN_DIFF] THEN
  ASM SET_TAC[]);;

let DERIVED_SET_OF_TOPSPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool.
        (indiscrete_topology u) derived_set_of u =
        if ?a. u SUBSET {a} then {} else u`,
  GEN_TAC THEN REWRITE_TAC[DERIVED_SET_OF_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[GSYM DISJOINT_EMPTY_REFL; INTER_IDEMPOT] THEN
  REWRITE_TAC[DIFF_EQ_EMPTY; COND_ID]);;

let PERFECT_SET_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        (indiscrete_topology u) derived_set_of s = s <=>
        s = {} \/ s = u /\ ~(?a.  u SUBSET {a})`,
  REPEAT GEN_TAC THEN ASM_CASES_TAC `s:A->bool = {}` THEN
  ASM_REWRITE_TAC[DERIVED_SET_OF_EMPTY] THEN
  REWRITE_TAC[DERIVED_SET_OF_INDISCRETE_TOPOLOGY] THEN
  ASM_CASES_TAC `s:A->bool = u` THENL [ALL_TAC; ASM SET_TAC[]] THEN
  FIRST_X_ASSUM SUBST_ALL_TAC THEN
  ASM_REWRITE_TAC[GSYM DISJOINT_EMPTY_REFL; INTER_IDEMPOT] THEN
  COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN ASM SET_TAC[]);;

let CONTINUOUS_MAP_INTO_INDISCRETE_TOPOLOGY = prove
 (`!(f:A->B) top u.
        continuous_map (top,indiscrete_topology u) f <=>
        IMAGE f (topspace top) SUBSET u`,
  REPEAT GEN_TAC THEN
  REWRITE_TAC[continuous_map; OPEN_IN_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TAUT `p \/ q ==> r <=> (p ==> r) /\ (q ==> r)`] THEN
  SIMP_TAC[NOT_IN_EMPTY; EMPTY_GSPEC; OPEN_IN_EMPTY] THEN
  REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; FORALL_UNWIND_THM2] THEN
  REWRITE_TAC[TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TAUT `(p /\ q <=> p) <=> p ==> q`] THEN
  SIMP_TAC[TAUT `p /\ q <=> ~(p ==> ~q)`] THEN
  REWRITE_TAC[IN_GSPEC; OPEN_IN_TOPSPACE]);;

let CONTINUOUS_MAP_FROM_INDISCRETE_TOPOLOGY = prove
 (`!top u (f:A->B).
        t1_space top
        ==> (continuous_map(indiscrete_topology u,top) f <=>
             u = {} \/ ?a. a IN topspace top /\ !x. x IN u ==> f x = a)`,
  REWRITE_TAC[T1_SPACE_CLOSED_IN_SING] THEN REPEAT STRIP_TAC THEN
  ASM_CASES_TAC `u:A->bool = {}` THEN
  ASM_REWRITE_TAC[CONTINUOUS_MAP_CLOSED_IN; TOPSPACE_INDISCRETE_TOPOLOGY;
    CLOSED_IN_INDISCRETE_TOPOLOGY; NOT_IN_EMPTY; EMPTY_GSPEC] THEN
  EQ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
  STRIP_TAC THEN MATCH_MP_TAC(SET_RULE
   `~(u = {}) /\
    (!x. x IN u ==> f x IN v) /\
    (!x y. x IN u /\ y IN u ==> f x = f y)
    ==> ?a. a IN v /\ (!x. x IN u ==> f x = a)`) THEN
  ASM_REWRITE_TAC[] THEN
  MAP_EVERY X_GEN_TAC [`a:A`; `b:A`] THEN STRIP_TAC THEN
  FIRST_X_ASSUM(fun th ->
    MP_TAC(SPEC `{(f:A->B) b}` th) THEN MP_TAC(SPEC `{(f:A->B) a}` th)) THEN
  ASM_SIMP_TAC[] THEN ASM SET_TAC[]);;

let PATH_CONNECTED_SPACE_INDISCRETE_TOPOLOGY = prove
 (`!u:A->bool. path_connected_space(indiscrete_topology u)`,
  REPEAT GEN_TAC THEN REWRITE_TAC[path_connected_space] THEN
  REWRITE_TAC[path_in; CONTINUOUS_MAP_INTO_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_EUCLIDEANREAL_SUBTOPOLOGY] THEN
  MAP_EVERY X_GEN_TAC [`x:A`; `y:A`] THEN STRIP_TAC THEN
  EXISTS_TAC `(\i. if i = &0 then x else y):real->A` THEN
  REWRITE_TAC[SUBSET; FORALL_IN_IMAGE] THEN
  CONV_TAC REAL_RAT_REDUCE_CONV THEN ASM SET_TAC[]);;

let PATH_CONNECTED_IN_INDISCRETE_TOPOLOGY = prove
 (`!u s:A->bool.
        path_connected_in (indiscrete_topology u) s <=> s SUBSET u`,
  REWRITE_TAC[path_connected_in; PATH_CONNECTED_SPACE_INDISCRETE_TOPOLOGY;
              SUBTOPOLOGY_INDISCRETE_TOPOLOGY; TOPSPACE_INDISCRETE_TOPOLOGY]);;

let NEIGHBOURHOOD_BASE_OF_INDISCRETE_TOPOLOGY = prove
 (`!P u:A->bool.
        neighbourhood_base_of P (indiscrete_topology u) <=>
        u = {} \/ P u`,
  REWRITE_TAC[NEIGHBOURHOOD_BASE_OF; OPEN_IN_INDISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[TAUT
   `(p \/ q) /\ r ==> s <=> (p ==> r ==> s) /\ (q ==> r ==> s)`] THEN
  SIMP_TAC[IN_ELIM_THM; RIGHT_FORALL_IMP_THM; NOT_IN_EMPTY] THEN
  REWRITE_TAC[FORALL_UNWIND_THM2; RIGHT_OR_DISTRIB] THEN
  REWRITE_TAC[EXISTS_OR_THM; RIGHT_EXISTS_AND_THM; UNWIND_THM2] THEN
  REWRITE_TAC[NOT_IN_EMPTY; SUBSET_ANTISYM_EQ] THEN
  ONCE_REWRITE_TAC[TAUT `p /\ q /\ r <=> r /\ p /\ q`] THEN
  SIMP_TAC[UNWIND_THM1] THEN SET_TAC[]);;

(* ------------------------------------------------------------------------- *)
(* Finite-complement (cofinite) topology.                                    *)
(* ------------------------------------------------------------------------- *)

let cofinite_topology = new_definition
 `cofinite_topology (u:A->bool) =
        topology ({} INSERT {s | s SUBSET u /\ FINITE(u DIFF s)})`;;

let OPEN_IN_COFINITE_TOPOLOGY = prove
 (`!u s:A->bool.
        open_in (cofinite_topology u) s <=>
        s = {} \/ s SUBSET u /\ FINITE(u DIFF s)`,
  REPEAT GEN_TAC THEN REWRITE_TAC[cofinite_topology] THEN
  W(MP_TAC o fst o EQ_IMP_RULE o PART_MATCH (lhand o rand)
     (CONJUNCT2 topology_tybij) o rator o lhand o snd) THEN
  ANTS_TAC THENL
   [REWRITE_TAC[istopology];
    DISCH_THEN SUBST1_TAC THEN
    GEN_REWRITE_TAC LAND_CONV [GSYM IN] THEN
    REWRITE_TAC[IN_ELIM_THM; IN_INSERT]] THEN
  REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ; FORALL_IN_INSERT] THEN
  REWRITE_TAC[IN_INSERT; INTER_EMPTY] THEN CONJ_TAC THENL
   [REWRITE_TAC[IN_ELIM_THM] THEN
    X_GEN_TAC `s:A->bool` THEN STRIP_TAC THEN
    X_GEN_TAC `t:A->bool` THEN STRIP_TAC THEN DISJ2_TAC THEN
    REWRITE_TAC[SET_RULE `u DIFF s INTER t = (u DIFF s) UNION (u DIFF t)`] THEN
    ASM_SIMP_TAC[FINITE_UNION] THEN ASM SET_TAC[];
    X_GEN_TAC `k:(A->bool)->bool` THEN REWRITE_TAC[EMPTY_UNIONS] THEN
    REWRITE_TAC[TAUT `p ==> q \/ r <=> p /\ ~q ==> r`] THEN
    DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
     `k SUBSET a INSERT s /\ ~(!x. x IN k ==> x = a)
      ==> k DELETE a SUBSET s /\ ~(k DELETE a = {})`)) THEN
    ONCE_REWRITE_TAC[GSYM UNIONS_DELETE_EMPTY] THEN
    SPEC_TAC(`(k DELETE {}):(A->bool)->bool`,`v:(A->bool)->bool`) THEN
    GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [SUBSET] THEN
    SIMP_TAC[IN_ELIM_THM; UNIONS_SUBSET] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(X_CHOOSE_TAC `s:A->bool` o
      REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
    MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `u DIFF s:A->bool` THEN
    ASM_SIMP_TAC[] THEN ASM SET_TAC[]]);;

let TOPSPACE_COFINITE_TOPOLOGY = prove
 (`!u:A->bool. topspace(cofinite_topology u) = u`,
  GEN_TAC THEN REWRITE_TAC[topspace; OPEN_IN_COFINITE_TOPOLOGY] THEN
  MATCH_MP_TAC(SET_RULE
   `(!s. P s ==> s SUBSET u) /\ P u ==> UNIONS {s | P s} = u`) THEN
  REWRITE_TAC[DIFF_EQ_EMPTY; FINITE_EMPTY] THEN SET_TAC[]);;

let CLOSED_IN_COFINITE_TOPOLOGY = prove
 (`!u s:A->bool.
        closed_in (cofinite_topology u) s <=>
        s = u \/ s SUBSET u /\ FINITE s`,
  REWRITE_TAC[closed_in; OPEN_IN_COFINITE_TOPOLOGY;
              TOPSPACE_COFINITE_TOPOLOGY] THEN
  REPEAT GEN_TAC THEN
  ASM_CASES_TAC `(s:A->bool) SUBSET u` THEN
  ASM_SIMP_TAC[SET_RULE `s SUBSET u ==> u DIFF (u DIFF s) = s`] THEN
  ASM SET_TAC[]);;

let T1_SPACE_COFINITE_TOPOLOGY = prove
 (`!u:A->bool. t1_space(cofinite_topology u)`,
  REWRITE_TAC[T1_SPACE_CLOSED_IN_SING; CLOSED_IN_COFINITE_TOPOLOGY] THEN
  SIMP_TAC[FINITE_SING; SING_SUBSET; TOPSPACE_COFINITE_TOPOLOGY]);;

let T1_SPACE_COFINITE_TOPOLOGY_MINIMAL = prove
 (`!top s:A->bool.
        t1_space top /\ closed_in (cofinite_topology(topspace top)) s
        ==> closed_in top s`,
  REWRITE_TAC[CLOSED_IN_COFINITE_TOPOLOGY] THEN
  MESON_TAC[T1_SPACE_CLOSED_IN_FINITE; CLOSED_IN_TOPSPACE]);;

let COFINITE_EQ_DISCRETE_TOPOLOGY = prove
 (`!u:A->bool. FINITE u ==> cofinite_topology u = discrete_topology u`,
  SIMP_TAC[TOPOLOGY_EQ; OPEN_IN_DISCRETE_TOPOLOGY; OPEN_IN_COFINITE_TOPOLOGY;
           FINITE_DIFF] THEN
  SET_TAC[]);;

let CONNECTED_IN_COFINITE_TOPOLOGY = prove
 (`!u s:A->bool.
        INFINITE s /\ s SUBSET u ==> connected_in (cofinite_topology u) s`,
  REWRITE_TAC[CONNECTED_IN_CLOSED_IN; CLOSED_IN_COFINITE_TOPOLOGY] THEN
  SIMP_TAC[TOPSPACE_COFINITE_TOPOLOGY] THEN REPEAT STRIP_TAC THENL
   [ASM SET_TAC[]; ASM SET_TAC[]; ASM SET_TAC[];
    ASM_MESON_TAC[INFINITE; FINITE_SUBSET; FINITE_UNION]]);;

let CONNECTED_SPACE_COFINITE_TOPOLOGY = prove
 (`!u:A->bool.
        connected_space(cofinite_topology u) <=>
        (?a. u SUBSET {a}) \/ INFINITE u`,
  GEN_TAC THEN ASM_CASES_TAC `FINITE(u:A->bool)` THEN
  ASM_SIMP_TAC[INFINITE; COFINITE_EQ_DISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[CONNECTED_SPACE_DISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[GSYM CONNECTED_IN_TOPSPACE] THEN
  MATCH_MP_TAC CONNECTED_IN_COFINITE_TOPOLOGY THEN
  ASM_REWRITE_TAC[INFINITE; TOPSPACE_COFINITE_TOPOLOGY; SUBSET_REFL]);;

let COMPACT_IN_COFINITE_TOPOLOGY = prove
 (`!u s:A->bool. compact_in(cofinite_topology u) s <=> s SUBSET u`,
  REPEAT GEN_TAC THEN
  REWRITE_TAC[COMPACT_IN_FIP; CLOSED_IN_COFINITE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_COFINITE_TOPOLOGY] THEN
  ASM_CASES_TAC `(s:A->bool) SUBSET u` THEN ASM_REWRITE_TAC[] THEN
  X_GEN_TAC `U:(A->bool)->bool` THEN STRIP_TAC THEN
  ASM_CASES_TAC `FINITE(U:(A->bool)->bool)` THEN
  ASM_SIMP_TAC[SUBSET_REFL] THEN
  SUBGOAL_THEN `?k:A->bool. k IN U /\ k SUBSET u /\ FINITE k`
  STRIP_ASSUME_TAC THENL
   [SUBGOAL_THEN `~((U:(A->bool)->bool) SUBSET {u})` MP_TAC THENL
     [ASM_MESON_TAC[FINITE_SUBSET; FINITE_SING];
      REWRITE_TAC[SUBSET; IN_SING] THEN ASM SET_TAC[]];
    ALL_TAC] THEN
  SUBGOAL_THEN `?V. V SUBSET U /\ FINITE V /\ INTERS U :A->bool = INTERS V`
  MP_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
  SUBGOAL_THEN `U = k INSERT (U DELETE (k:A->bool))` SUBST1_TAC THENL
   [ASM SET_TAC[]; REWRITE_TAC[INTER_INTERS; INTERS_INSERT]] THEN
  ASM_SIMP_TAC[SET_RULE `a IN s ==> (s DELETE a = {} <=> s = {a})`] THEN
  COND_CASES_TAC THENL [ASM_MESON_TAC[FINITE_SING]; ALL_TAC] THEN
  MATCH_MP_TAC(MESON[] `!k. (?s. P(k INSERT k INSERT s)) ==> (?s. P s)`) THEN
  EXISTS_TAC `k:A->bool` THEN ONCE_REWRITE_TAC[INTERS_INSERT] THEN
  REWRITE_TAC[INTER_INTERS; FINITE_INSERT; NOT_INSERT_EMPTY] THEN
  SUBGOAL_THEN `FINITE {k INTER t:A->bool | t | t IN U DELETE k}` MP_TAC THENL
   [MATCH_MP_TAC FINITE_SUBSET THEN
    EXISTS_TAC `{l:A->bool | l SUBSET k}` THEN
    ASM_SIMP_TAC[FINITE_POWERSET] THEN
    GEN_REWRITE_TAC I [SUBSET] THEN REWRITE_TAC[FORALL_IN_GSPEC] THEN
    REWRITE_TAC[IN_ELIM_THM; INTER_SUBSET];
    REWRITE_TAC[SIMPLE_IMAGE] THEN
    GEN_REWRITE_TAC LAND_CONV [FINITE_IMAGE_EQ] THEN
    MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `V:(A->bool)->bool` THEN
    ASM_CASES_TAC `V:(A->bool)->bool = {}` THEN
    ASM_REWRITE_TAC[IMAGE_CLAUSES; IMAGE_EQ_EMPTY] THENL
     [ASM_MESON_TAC[FINITE_EMPTY; FINITE_DELETE]; STRIP_TAC] THEN
    CONJ_TAC THENL [ASM SET_TAC[]; ASM_REWRITE_TAC[]] THEN
    REWRITE_TAC[INTER_IDEMPOT; INTER_INTERS; INTERS_INSERT] THEN
    ASM_REWRITE_TAC[IMAGE_EQ_EMPTY; SET_RULE
     `{g y | y IN IMAGE f s} = {g(f x) | x IN s}`] THEN
    REWRITE_TAC[SIMPLE_IMAGE; SET_RULE `k INTER k INTER s = k INTER s`]]);;

let COMPACT_SPACE_COFINITE_TOPOLOGY = prove
 (`!u:A->bool. compact_space(cofinite_topology u)`,
  REWRITE_TAC[compact_space; COMPACT_IN_COFINITE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_COFINITE_TOPOLOGY; SUBSET_REFL]);;

let HAUSDORFF_SPACE_SUBTOPOLOGY_COFINITE_TOPOLOGY = prove
 (`!u s:A->bool.
        hausdorff_space (subtopology (cofinite_topology u) s) <=>
        FINITE(u INTER s)`,
  REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[SUBTOPOLOGY_RESTRICT] THEN
  REWRITE_TAC[TOPSPACE_COFINITE_TOPOLOGY] THEN
  MP_TAC(SET_RULE `u INTER (s:A->bool) SUBSET u`) THEN
  SPEC_TAC(`u INTER (s:A->bool)`,`s:A->bool`) THEN
  REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
   [ASM_CASES_TAC `?a:A. s SUBSET {a}` THENL
     [ASM_MESON_TAC[FINITE_SUBSET; FINITE_SING]; ALL_TAC] THEN
    FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
     `~(?a. s SUBSET {a}) ==> ?a b. a IN s /\ b IN s /\ ~(a = b)`)) THEN
    REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
    MAP_EVERY X_GEN_TAC [`a:A`; `b:A`] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(MP_TAC o SPECL [`a:A`; `b:A`] o
      GEN_REWRITE_RULE I [hausdorff_space]) THEN
    ASM_SIMP_TAC[TOPSPACE_SUBTOPOLOGY_SUBSET; TOPSPACE_COFINITE_TOPOLOGY] THEN
    REWRITE_TAC[LEFT_IMP_EXISTS_THM; RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
    REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_ALT; FORALL_IN_GSPEC] THEN
    REWRITE_TAC[IN_INTER; OPEN_IN_COFINITE_TOPOLOGY] THEN
    X_GEN_TAC `t:A->bool` THEN STRIP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
    X_GEN_TAC `t':A->bool` THEN STRIP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
    REPEAT STRIP_TAC THEN MATCH_MP_TAC FINITE_SUBSET THEN
    EXISTS_TAC `(u DIFF t) UNION (u DIFF t'):A->bool` THEN
    ASM_REWRITE_TAC[FINITE_UNION] THEN ASM SET_TAC[];
    ASM_SIMP_TAC[hausdorff_space; TOPSPACE_SUBTOPOLOGY_SUBSET;
                 TOPSPACE_COFINITE_TOPOLOGY] THEN
    MAP_EVERY X_GEN_TAC [`x:A`; `y:A`] THEN STRIP_TAC THEN
    REWRITE_TAC[RIGHT_EXISTS_AND_THM; OPEN_IN_SUBTOPOLOGY_ALT] THEN
    REWRITE_TAC[EXISTS_IN_GSPEC; OPEN_IN_COFINITE_TOPOLOGY] THEN
    REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
    EXISTS_TAC `(x:A) INSERT (u DIFF s)` THEN
    EXISTS_TAC `(y:A) INSERT (u DIFF s)` THEN
    REWRITE_TAC[NOT_INSERT_EMPTY] THEN
    REPEAT CONJ_TAC THEN
    TRY(MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `s:A->bool`) THEN
    ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;

let HAUSDORFF_SPACE_COFINITE_TOPOLOGY = prove
 (`!u:A->bool. hausdorff_space(cofinite_topology u) <=> FINITE u`,
  GEN_TAC THEN ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_TOPSPACE] THEN
  REWRITE_TAC[HAUSDORFF_SPACE_SUBTOPOLOGY_COFINITE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_COFINITE_TOPOLOGY; INTER_IDEMPOT]);;

(* ------------------------------------------------------------------------- *)
(* Countable-complement (cocountable) topology.                              *)
(* ------------------------------------------------------------------------- *)

let cocountable_topology = new_definition
 `cocountable_topology (u:A->bool) =
        topology ({} INSERT {s | s SUBSET u /\ COUNTABLE(u DIFF s)})`;;

let OPEN_IN_COCOUNTABLE_TOPOLOGY = prove
 (`!u s:A->bool.
        open_in (cocountable_topology u) s <=>
        s = {} \/ s SUBSET u /\ COUNTABLE(u DIFF s)`,
  REPEAT GEN_TAC THEN REWRITE_TAC[cocountable_topology] THEN
  W(MP_TAC o fst o EQ_IMP_RULE o PART_MATCH (lhand o rand)
     (CONJUNCT2 topology_tybij) o rator o lhand o snd) THEN
  ANTS_TAC THENL
   [REWRITE_TAC[istopology];
    DISCH_THEN SUBST1_TAC THEN
    GEN_REWRITE_TAC LAND_CONV [GSYM IN] THEN
    REWRITE_TAC[IN_ELIM_THM; IN_INSERT]] THEN
  REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ; FORALL_IN_INSERT] THEN
  REWRITE_TAC[IN_INSERT; INTER_EMPTY] THEN CONJ_TAC THENL
   [REWRITE_TAC[IN_ELIM_THM] THEN
    X_GEN_TAC `s:A->bool` THEN STRIP_TAC THEN
    X_GEN_TAC `t:A->bool` THEN STRIP_TAC THEN DISJ2_TAC THEN
    REWRITE_TAC[SET_RULE `u DIFF s INTER t = (u DIFF s) UNION (u DIFF t)`] THEN
    ASM_SIMP_TAC[COUNTABLE_UNION] THEN ASM SET_TAC[];
    X_GEN_TAC `k:(A->bool)->bool` THEN REWRITE_TAC[EMPTY_UNIONS] THEN
    REWRITE_TAC[TAUT `p ==> q \/ r <=> p /\ ~q ==> r`] THEN
    DISCH_THEN(MP_TAC o MATCH_MP (SET_RULE
     `k SUBSET a INSERT s /\ ~(!x. x IN k ==> x = a)
      ==> k DELETE a SUBSET s /\ ~(k DELETE a = {})`)) THEN
    ONCE_REWRITE_TAC[GSYM UNIONS_DELETE_EMPTY] THEN
    SPEC_TAC(`(k DELETE {}):(A->bool)->bool`,`v:(A->bool)->bool`) THEN
    GEN_TAC THEN GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [SUBSET] THEN
    SIMP_TAC[IN_ELIM_THM; UNIONS_SUBSET] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(X_CHOOSE_TAC `s:A->bool` o
      REWRITE_RULE[GSYM MEMBER_NOT_EMPTY]) THEN
    MATCH_MP_TAC COUNTABLE_SUBSET THEN EXISTS_TAC `u DIFF s:A->bool` THEN
    ASM_SIMP_TAC[] THEN ASM SET_TAC[]]);;

let TOPSPACE_COCOUNTABLE_TOPOLOGY = prove
 (`!u:A->bool. topspace(cocountable_topology u) = u`,
  GEN_TAC THEN REWRITE_TAC[topspace; OPEN_IN_COCOUNTABLE_TOPOLOGY] THEN
  MATCH_MP_TAC(SET_RULE
   `(!s. P s ==> s SUBSET u) /\ P u ==> UNIONS {s | P s} = u`) THEN
  REWRITE_TAC[DIFF_EQ_EMPTY; COUNTABLE_EMPTY] THEN SET_TAC[]);;

let CLOSED_IN_COCOUNTABLE_TOPOLOGY = prove
 (`!u s:A->bool.
        closed_in (cocountable_topology u) s <=>
        s = u \/ s SUBSET u /\ COUNTABLE s`,
  REWRITE_TAC[closed_in; OPEN_IN_COCOUNTABLE_TOPOLOGY;
              TOPSPACE_COCOUNTABLE_TOPOLOGY] THEN
  REPEAT GEN_TAC THEN
  ASM_CASES_TAC `(s:A->bool) SUBSET u` THEN
  ASM_SIMP_TAC[SET_RULE `s SUBSET u ==> u DIFF (u DIFF s) = s`] THEN
  ASM SET_TAC[]);;

let T1_SPACE_COCOUNTABLE_TOPOLOGY = prove
 (`!u:A->bool. t1_space(cocountable_topology u)`,
  REWRITE_TAC[T1_SPACE_CLOSED_IN_SING; CLOSED_IN_COCOUNTABLE_TOPOLOGY] THEN
  SIMP_TAC[COUNTABLE_SING; SING_SUBSET; TOPSPACE_COCOUNTABLE_TOPOLOGY]);;

let COCOUNTABLE_EQ_DISCRETE_TOPOLOGY = prove
 (`!u:A->bool. COUNTABLE u ==> cocountable_topology u = discrete_topology u`,
  SIMP_TAC[TOPOLOGY_EQ; OPEN_IN_DISCRETE_TOPOLOGY; OPEN_IN_COCOUNTABLE_TOPOLOGY;
           COUNTABLE_DIFF] THEN
  SET_TAC[]);;

let CONNECTED_IN_COCOUNTABLE_TOPOLOGY = prove
 (`!u s:A->bool.
        ~COUNTABLE s /\ s SUBSET u
        ==> connected_in (cocountable_topology u) s`,
  REWRITE_TAC[CONNECTED_IN_CLOSED_IN; CLOSED_IN_COCOUNTABLE_TOPOLOGY] THEN
  SIMP_TAC[TOPSPACE_COCOUNTABLE_TOPOLOGY] THEN REPEAT STRIP_TAC THENL
   [ASM SET_TAC[]; ASM SET_TAC[]; ASM SET_TAC[];
    ASM_MESON_TAC[COUNTABLE_SUBSET; COUNTABLE_UNION]]);;

let CONNECTED_SPACE_COCOUNTABLE_TOPOLOGY = prove
 (`!u:A->bool.
        connected_space(cocountable_topology u) <=>
        (?a. u SUBSET {a}) \/ ~COUNTABLE u`,
  GEN_TAC THEN ASM_CASES_TAC `COUNTABLE(u:A->bool)` THEN
  ASM_SIMP_TAC[COCOUNTABLE_EQ_DISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[CONNECTED_SPACE_DISCRETE_TOPOLOGY] THEN
  REWRITE_TAC[GSYM CONNECTED_IN_TOPSPACE] THEN
  MATCH_MP_TAC CONNECTED_IN_COCOUNTABLE_TOPOLOGY THEN
  ASM_REWRITE_TAC[TOPSPACE_COCOUNTABLE_TOPOLOGY; SUBSET_REFL]);;

let COMPACT_IN_COCOUNTABLE_TOPOLOGY = prove
 (`!u s:A->bool. compact_in(cocountable_topology u) s <=>
                 s SUBSET u /\ FINITE s`,
  REPEAT GEN_TAC THEN ASM_CASES_TAC `(s:A->bool) SUBSET u` THENL
   [EQ_TAC THEN
    ASM_SIMP_TAC[FINITE_IMP_COMPACT_IN; TOPSPACE_COCOUNTABLE_TOPOLOGY];
    ASM_MESON_TAC[COMPACT_IN_SUBSET_TOPSPACE;
                  TOPSPACE_COCOUNTABLE_TOPOLOGY]] THEN
  GEN_REWRITE_TAC I [GSYM CONTRAPOS_THM] THEN
  REWRITE_TAC[FINITE_CARD_LT; CARD_NOT_LT; CARD_LE_EQ_SUBSET] THEN
  DISCH_THEN(X_CHOOSE_THEN `t:A->bool` STRIP_ASSUME_TAC) THEN
  FIRST_ASSUM(MP_TAC o MATCH_MP CARD_FINITE_CONG) THEN
  REWRITE_TAC[REWRITE_RULE[INFINITE] num_INFINITE] THEN
  ASM_CASES_TAC `t:A->bool = {}` THEN ASM_REWRITE_TAC[FINITE_EMPTY] THEN
  DISCH_TAC THEN
  REWRITE_TAC[COMPACT_IN_FIP; CLOSED_IN_COCOUNTABLE_TOPOLOGY] THEN
  ASM_REWRITE_TAC[TOPSPACE_COCOUNTABLE_TOPOLOGY] THEN
  DISCH_THEN(MP_TAC o SPEC `{t DIFF {x:A} | x | x IN t}`) THEN
  REWRITE_TAC[NOT_IMP; FORALL_IN_GSPEC] THEN REPEAT CONJ_TAC THENL
   [X_GEN_TAC `a:A` THEN DISCH_TAC THEN DISJ2_TAC THEN
    CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
    MATCH_MP_TAC COUNTABLE_SUBSET THEN EXISTS_TAC `t:A->bool` THEN
    REWRITE_TAC[SUBSET_DIFF; COUNTABLE; ge_c] THEN
    ASM_MESON_TAC[CARD_EQ_SYM; CARD_EQ_IMP_LE];
    ALL_TAC;
    REWRITE_TAC[INTERS_GSPEC] THEN ASM SET_TAC[]] THEN
  REWRITE_TAC[FORALL_FINITE_SUBSET_IMAGE; SIMPLE_IMAGE] THEN
  X_GEN_TAC `v:A->bool` THEN STRIP_TAC THEN
  FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
    `t SUBSET s ==> ~(t INTER u = {}) ==> ~(s INTER u = {})`)) THEN
  REWRITE_TAC[SET_RULE
   `IMAGE (\x. t DIFF {x}) v = {t DIFF u | u IN IMAGE (\x. {x}) v}`] THEN
  REWRITE_TAC[GSYM DIFF_UNIONS] THEN
  REWRITE_TAC[GSYM SIMPLE_IMAGE; UNIONS_SINGS] THEN
  ASM_SIMP_TAC[SET_RULE `v SUBSET t ==> (t DIFF v = {} <=> t = v)`] THEN
  ASM_MESON_TAC[]);;

let COMPACT_SPACE_COCOUNTABLE_TOPOLOGY = prove
 (`!u:A->bool. compact_space(cocountable_topology u) <=> FINITE u`,
  REWRITE_TAC[compact_space; COMPACT_IN_COCOUNTABLE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_COCOUNTABLE_TOPOLOGY; SUBSET_REFL]);;

let HAUSDORFF_SPACE_SUBTOPOLOGY_COCOUNTABLE_TOPOLOGY = prove
 (`!u s:A->bool.
        hausdorff_space (subtopology (cocountable_topology u) s) <=>
        COUNTABLE(u INTER s)`,
  REPEAT GEN_TAC THEN ONCE_REWRITE_TAC[SUBTOPOLOGY_RESTRICT] THEN
  REWRITE_TAC[TOPSPACE_COCOUNTABLE_TOPOLOGY] THEN
  MP_TAC(SET_RULE `u INTER (s:A->bool) SUBSET u`) THEN
  SPEC_TAC(`u INTER (s:A->bool)`,`s:A->bool`) THEN
  REPEAT STRIP_TAC THEN EQ_TAC THEN DISCH_TAC THENL
   [ASM_CASES_TAC `?a:A. s SUBSET {a}` THENL
     [ASM_MESON_TAC[COUNTABLE_SUBSET; COUNTABLE_SING]; ALL_TAC] THEN
    FIRST_X_ASSUM(MP_TAC o MATCH_MP (SET_RULE
     `~(?a. s SUBSET {a}) ==> ?a b. a IN s /\ b IN s /\ ~(a = b)`)) THEN
    REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
    MAP_EVERY X_GEN_TAC [`a:A`; `b:A`] THEN STRIP_TAC THEN
    FIRST_X_ASSUM(MP_TAC o SPECL [`a:A`; `b:A`] o
      GEN_REWRITE_RULE I [hausdorff_space]) THEN
    ASM_SIMP_TAC[TOPSPACE_SUBTOPOLOGY_SUBSET;
                 TOPSPACE_COCOUNTABLE_TOPOLOGY] THEN
    REWRITE_TAC[LEFT_IMP_EXISTS_THM; RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
    REWRITE_TAC[OPEN_IN_SUBTOPOLOGY_ALT; FORALL_IN_GSPEC] THEN
    REWRITE_TAC[IN_INTER; OPEN_IN_COCOUNTABLE_TOPOLOGY] THEN
    X_GEN_TAC `t:A->bool` THEN STRIP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
    X_GEN_TAC `t':A->bool` THEN STRIP_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
    REPEAT STRIP_TAC THEN MATCH_MP_TAC COUNTABLE_SUBSET THEN
    EXISTS_TAC `(u DIFF t) UNION (u DIFF t'):A->bool` THEN
    ASM_REWRITE_TAC[COUNTABLE_UNION] THEN ASM SET_TAC[];
    ASM_SIMP_TAC[hausdorff_space; TOPSPACE_SUBTOPOLOGY_SUBSET;
                 TOPSPACE_COCOUNTABLE_TOPOLOGY] THEN
    MAP_EVERY X_GEN_TAC [`x:A`; `y:A`] THEN STRIP_TAC THEN
    REWRITE_TAC[RIGHT_EXISTS_AND_THM; OPEN_IN_SUBTOPOLOGY_ALT] THEN
    REWRITE_TAC[EXISTS_IN_GSPEC; OPEN_IN_COCOUNTABLE_TOPOLOGY] THEN
    REWRITE_TAC[RIGHT_AND_EXISTS_THM] THEN
    EXISTS_TAC `(x:A) INSERT (u DIFF s)` THEN
    EXISTS_TAC `(y:A) INSERT (u DIFF s)` THEN
    REWRITE_TAC[NOT_INSERT_EMPTY] THEN
    REPEAT CONJ_TAC THEN
    TRY(MATCH_MP_TAC COUNTABLE_SUBSET THEN EXISTS_TAC `s:A->bool`) THEN
    ASM_REWRITE_TAC[] THEN ASM SET_TAC[]]);;

let HAUSDORFF_SPACE_COCOUNTABLE_TOPOLOGY = prove
 (`!u:A->bool. hausdorff_space(cocountable_topology u) <=> COUNTABLE u`,
  GEN_TAC THEN ONCE_REWRITE_TAC[GSYM SUBTOPOLOGY_TOPSPACE] THEN
  REWRITE_TAC[HAUSDORFF_SPACE_SUBTOPOLOGY_COCOUNTABLE_TOPOLOGY] THEN
  REWRITE_TAC[TOPSPACE_COCOUNTABLE_TOPOLOGY; INTER_IDEMPOT]);;

let KC_SPACE_COCOUNTABLE_TOPOLOGY = prove
 (`!u:A->bool. kc_space(cocountable_topology u)`,
  REWRITE_TAC[kc_space; CLOSED_IN_COCOUNTABLE_TOPOLOGY;
              COMPACT_IN_COCOUNTABLE_TOPOLOGY] THEN
  SIMP_TAC[FINITE_IMP_COUNTABLE]);;
