(* ========================================================================= *)
(* Very basic set theory (using predicates as sets). *)
(* *)
(* John Harrison, University of Cambridge Computer Laboratory *)
(* *)
(* (c) Copyright, University of Cambridge 1998 *)
(* (c) Copyright, John Harrison 1998-2007 *)
(* (c) Copyright, Marco Maggesi 2012 *)
(* ========================================================================= *)
needs "int.ml";;
(* ------------------------------------------------------------------------- *)
(* Infix symbols for set operations. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("IN",(11,"right"));;
parse_as_infix("SUBSET",(12,"right"));;
parse_as_infix("PSUBSET",(12,"right"));;
parse_as_infix("INTER",(20,"right"));;
parse_as_infix("UNION",(16,"right"));;
parse_as_infix("DIFF",(18,"left"));;
parse_as_infix("INSERT",(21,"right"));;
parse_as_infix("DELETE",(21,"left"));;
parse_as_infix("HAS_SIZE",(12,"right"));;
parse_as_infix("<=_c",(12,"right"));;
parse_as_infix("<_c",(12,"right"));;
parse_as_infix(">=_c",(12,"right"));;
parse_as_infix(">_c",(12,"right"));;
parse_as_infix("=_c",(12,"right"));;
(* ------------------------------------------------------------------------- *)
(* Set membership. *)
(* ------------------------------------------------------------------------- *)
let IN = new_definition
`!P:A->bool. !x. x IN P <=> P x`;;
(* ------------------------------------------------------------------------- *)
(* Axiom of extensionality in this framework. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* General specification. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Rewrite rule for eliminating set-comprehension membership assertions. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* These two definitions are needed first, for the parsing of enumerations. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* The other basic operations. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Other basic predicates. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Finiteness. *)
(* ------------------------------------------------------------------------- *)
let FINITE_RULES,FINITE_INDUCT,FINITE_CASES =
new_inductive_definition
`FINITE (EMPTY:A->bool) /\
!(x:A) s. FINITE s ==> FINITE (x INSERT s)`;;
(* ------------------------------------------------------------------------- *)
(* Stuff concerned with functions. *)
(* ------------------------------------------------------------------------- *)
let IMAGE = new_definition
`IMAGE (f:A->B) s = { y | ?x. x IN s /\ (y = f x)}`;;
let INJ = new_definition
`INJ (f:A->B) s t <=>
(!x. x IN s ==> (f x) IN t) /\
(!x y. x IN s /\ y IN s /\ (f x = f y) ==> (x = y))`;;
let SURJ = new_definition
`SURJ (f:A->B) s t <=>
(!x. x IN s ==> (f x) IN t) /\
(!x. (x IN t) ==> ?y. y IN s /\ (f y = x))`;;
(* ------------------------------------------------------------------------- *)
(* Another funny thing. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Basic membership properties. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Basic property of the choice function. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Tactic to automate some routine set theory by reduction to FOL. *)
(* ------------------------------------------------------------------------- *)
let SET_TAC =
let PRESET_TAC =
POP_ASSUM_LIST(K ALL_TAC) THEN REPEAT COND_CASES_TAC THEN
REWRITE_TAC[EXTENSION; SUBSET; PSUBSET; DISJOINT; SING] THEN
REWRITE_TAC[NOT_IN_EMPTY; IN_UNIV; IN_UNION; IN_INTER; IN_DIFF; IN_INSERT;
IN_DELETE; IN_REST; IN_INTERS; IN_UNIONS; IN_IMAGE;
IN_ELIM_THM; IN] in
fun ths ->
(if ths = [] then ALL_TAC else MP_TAC(end_itlist CONJ ths)) THEN
PRESET_TAC THEN
MESON_TAC[];;
let SET_RULE tm = prove(tm,SET_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Misc. theorems. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* The empty set. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* The universal set. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Set inclusion. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Proper subset. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Union. *)
(* ------------------------------------------------------------------------- *)
let FORALL_SUBSET_UNION = prove
(`!t u:A->bool.
(!s. s
SUBSET t
UNION u ==> P s) <=>
(!t' u'. t'
SUBSET t /\ u'
SUBSET u ==> P(t'
UNION u'))`,
REPEAT GEN_TAC THEN EQ_TAC THENL
[REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THEN ASM SET_TAC[];
DISCH_TAC THEN X_GEN_TAC `s:A->bool` THEN DISCH_TAC THEN
FIRST_ASSUM(MP_TAC o SPECL [`s
INTER t:A->bool`; `s
INTER u:A->bool`]) THEN
ANTS_TAC THENL [ALL_TAC; MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC] THEN
ASM SET_TAC[]]);;
(* ------------------------------------------------------------------------- *)
(* Intersection. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Distributivity. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Disjoint sets. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Set difference. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Insertion and deletion. *)
(* ------------------------------------------------------------------------- *)
let DECOMPOSITION = prove
(`!s:A->bool. !x. x
IN s <=> ?t. (s = x
INSERT t) /\ ~(x
IN t)`,
REPEAT GEN_TAC THEN EQ_TAC THEN STRIP_TAC THEN
ASM_REWRITE_TAC[
IN_INSERT] THEN EXISTS_TAC `s
DELETE x:A` THEN
POP_ASSUM MP_TAC THEN SET_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Multiple union. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Multiple intersection. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Image. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Misc lemmas. *)
(* ------------------------------------------------------------------------- *)
let SING_GSPEC = prove
(`(!a. {x | x = a} = {a}) /\
(!a. {x | a = x} = {a})`,
SET_TAC[]);;
let FORALL_IN_GSPEC = prove
(`(!P f. (!z. z
IN {f x | P x} ==> Q z) <=> (!x. P x ==> Q(f x))) /\
(!P f. (!z. z
IN {f x y | P x y} ==> Q z) <=>
(!x y. P x y ==> Q(f x y))) /\
(!P f. (!z. z
IN {f w x y | P w x y} ==> Q z) <=>
(!w x y. P w x y ==> Q(f w x y))) /\
(!P f. (!z. z
IN {f v w x y | P v w x y} ==> Q z) <=>
(!v w x y. P v w x y ==> Q(f v w x y)))`,
SET_TAC[]);;
let EXISTS_IN_GSPEC = prove
(`(!P f. (?z. z
IN {f x | P x} /\ Q z) <=> (?x. P x /\ Q(f x))) /\
(!P f. (?z. z
IN {f x y | P x y} /\ Q z) <=>
(?x y. P x y /\ Q(f x y))) /\
(!P f. (?z. z
IN {f w x y | P w x y} /\ Q z) <=>
(?w x y. P w x y /\ Q(f w x y))) /\
(!P f. (?z. z
IN {f v w x y | P v w x y} /\ Q z) <=>
(?v w x y. P v w x y /\ Q(f v w x y)))`,
SET_TAC[]);;
let UNIONS_GSPEC = prove
(`(!P f.
UNIONS {f x | P x} = {a | ?x. P x /\ a
IN (f x)}) /\
(!P f.
UNIONS {f x y | P x y} = {a | ?x y. P x y /\ a
IN (f x y)}) /\
(!P f.
UNIONS {f x y z | P x y z} =
{a | ?x y z. P x y z /\ a
IN (f x y z)})`,
let INTERS_GSPEC = prove
(`(!P f.
INTERS {f x | P x} = {a | !x. P x ==> a
IN (f x)}) /\
(!P f.
INTERS {f x y | P x y} = {a | !x y. P x y ==> a
IN (f x y)}) /\
(!P f.
INTERS {f x y z | P x y z} =
{a | !x y z. P x y z ==> a
IN (f x y z)})`,
(* ------------------------------------------------------------------------- *)
(* Stronger form of induction is sometimes handy. *)
(* ------------------------------------------------------------------------- *)
let FINITE_INDUCT_STRONG = prove
(`!P:(A->bool)->bool.
P {} /\ (!x s. P s /\ ~(x
IN s) /\
FINITE s ==> P(x
INSERT s))
==> !s.
FINITE s ==> P s`,
GEN_TAC THEN STRIP_TAC THEN
SUBGOAL_THEN `!s:A->bool.
FINITE s ==>
FINITE s /\ P s` MP_TAC THENL
[ALL_TAC; MESON_TAC[]] THEN
MATCH_MP_TAC
FINITE_INDUCT THEN ASM_SIMP_TAC[
FINITE_RULES] THEN
REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN ASM_CASES_TAC `x:A
IN s` THENL
[SUBGOAL_THEN `x:A
INSERT s = s` (fun th -> ASM_REWRITE_TAC[th]) THEN
UNDISCH_TAC `x:A
IN s` THEN SET_TAC[];
FIRST_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]]);;
(* ------------------------------------------------------------------------- *)
(* Useful general properties of functions. *)
(* ------------------------------------------------------------------------- *)
let INJECTIVE_ON_ALT = prove
(`!P f. (!x y. P x /\ P y /\ f x = f y ==> x = y) <=>
(!x y. P x /\ P y ==> (f x = f y <=> x = y))`,
MESON_TAC[]);;
let INJECTIVE_ALT = prove
(`!f. (!x y. f x = f y ==> x = y) <=> (!x y. f x = f y <=> x = y)`,
MESON_TAC[]);;
let INJECTIVE_ON_LEFT_INVERSE = prove
(`!f s. (!x y. x
IN s /\ y
IN s /\ (f x = f y) ==> (x = y)) <=>
(?g. !x. x
IN s ==> (g(f(x)) = x))`,
let lemma = MESON[]
`(!x. x
IN s ==> (g(f(x)) = x)) <=>
(!y x. x
IN s /\ (y = f x) ==> (g y = x))` in
REWRITE_TAC[lemma; GSYM
SKOLEM_THM] THEN MESON_TAC[]);;
let FUNCTION_FACTORS_LEFT_GEN = prove
(`!P f g. (!x y. P x /\ P y /\ g x = g y ==> f x = f y) <=>
(?h. !x. P x ==> f(x) = h(g x))`,
ONCE_REWRITE_TAC[MESON[]
`(!x. P x ==> f(x) = g(k x)) <=> (!y x. P x /\ y = k x ==> f x = g y)`] THEN
REWRITE_TAC[GSYM
SKOLEM_THM] THEN MESON_TAC[]);;
let SURJECTIVE_FORALL_THM = prove
(`!f:A->B. (!y. ?x. f x = y) <=> (!P. (!x. P(f x)) <=> (!y. P y))`,
GEN_TAC THEN EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
DISCH_THEN(fun th -> ONCE_REWRITE_TAC[GSYM th]) THEN MESON_TAC[]);;
let SURJECTIVE_EXISTS_THM = prove
(`!f:A->B. (!y. ?x. f x = y) <=> (!P. (?x. P(f x)) <=> (?y. P y))`,
GEN_TAC THEN EQ_TAC THENL [MESON_TAC[]; ALL_TAC] THEN
DISCH_THEN(MP_TAC o SPEC `\y:B. !x:A. ~(f x = y)`) THEN MESON_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Basic combining theorems for finite sets. *)
(* ------------------------------------------------------------------------- *)
let FINITE_DELETE = prove
(`!(s:A->bool) x.
FINITE (s
DELETE x) <=>
FINITE s`,
REPEAT GEN_TAC THEN EQ_TAC THEN REWRITE_TAC[
FINITE_DELETE_IMP] THEN
ASM_CASES_TAC `x:A
IN s` THENL
[SUBGOAL_THEN `s = x
INSERT (s
DELETE x:A)`
(fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th]) THEN
REWRITE_TAC[
FINITE_INSERT] THEN POP_ASSUM MP_TAC THEN SET_TAC[];
SUBGOAL_THEN `s
DELETE x:A = s` (fun th -> REWRITE_TAC[th]) THEN
POP_ASSUM MP_TAC THEN SET_TAC[]]);;
(* ------------------------------------------------------------------------- *)
(* Recursion over finite sets; based on Ching-Tsun's code (archive 713). *)
(* ------------------------------------------------------------------------- *)
let FINREC = new_recursive_definition num_RECURSION
`(FINREC (f:A->B->B) b s a 0 <=> (s = {}) /\ (a = b)) /\
(FINREC (f:A->B->B) b s a (SUC n) <=>
?x c. x IN s /\
FINREC f b (s DELETE x) c n /\
(a = f x c))`;;
let FINREC_1_LEMMA = prove
(`!f b s a.
FINREC f b s a (SUC 0) <=> ?x. (s = {x}) /\ (a = f x b)`,
REWRITE_TAC[
FINREC] THEN
REPEAT GEN_TAC THEN AP_TERM_TAC THEN ABS_TAC THEN SET_TAC[]);;
let FINREC_SUC_LEMMA = prove
(`!(f:A->B->B) b.
(!x y s. ~(x = y) ==> (f x (f y s) = f y (f x s)))
==> !n s z.
FINREC f b s z (SUC n)
==> !x. x
IN s ==> ?w.
FINREC f b (s
DELETE x) w n /\
(z = f x w)`,
let lem = prove(`s DELETE (x:A) DELETE y = s DELETE y DELETE x`,SET_TAC[]) in
REPEAT GEN_TAC THEN DISCH_TAC THEN INDUCT_TAC THENL
[REWRITE_TAC[FINREC_1_LEMMA] THEN REWRITE_TAC[FINREC] THEN
REPEAT GEN_TAC THEN STRIP_TAC THEN STRIP_TAC THEN
ASM_REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY] THEN
DISCH_THEN SUBST1_TAC THEN EXISTS_TAC `b:B` THEN
ASM_REWRITE_TAC[] THEN SET_TAC[];
REPEAT GEN_TAC THEN
GEN_REWRITE_TAC LAND_CONV [FINREC] THEN
DISCH_THEN(X_CHOOSE_THEN `y:A` MP_TAC) THEN
DISCH_THEN(X_CHOOSE_THEN `c:B` STRIP_ASSUME_TAC) THEN
X_GEN_TAC `x:A` THEN DISCH_TAC THEN
ASM_CASES_TAC `x:A = y` THEN ASM_REWRITE_TAC[] THENL
[EXISTS_TAC `c:B` THEN ASM_REWRITE_TAC[];
UNDISCH_TAC `FINREC (f:A->B->B) b (s DELETE y) c (SUC n)` THEN
DISCH_THEN(ANTE_RES_THEN (MP_TAC o SPEC `x:A`)) THEN
ASM_REWRITE_TAC[IN_DELETE] THEN
DISCH_THEN(X_CHOOSE_THEN `v:B` STRIP_ASSUME_TAC) THEN
EXISTS_TAC `(f:A->B->B) y v` THEN ASM_REWRITE_TAC[FINREC] THEN
CONJ_TAC THENL
[MAP_EVERY EXISTS_TAC [`y:A`; `v:B`] THEN
ONCE_REWRITE_TAC[lem] THEN ASM_REWRITE_TAC[IN_DELETE];
FIRST_ASSUM MATCH_MP_TAC THEN ASM_REWRITE_TAC[]]]]);;
let FINREC_UNIQUE_LEMMA = prove
(`!(f:A->B->B) b.
(!x y s. ~(x = y) ==> (f x (f y s) = f y (f x s)))
==> !n1 n2 s a1 a2.
FINREC f b s a1 n1 /\
FINREC f b s a2 n2
==> (a1 = a2) /\ (n1 = n2)`,
REPEAT GEN_TAC THEN DISCH_TAC THEN
INDUCT_TAC THEN INDUCT_TAC THENL
[REWRITE_TAC[
FINREC] THEN MESON_TAC[
NOT_IN_EMPTY];
REWRITE_TAC[
FINREC] THEN MESON_TAC[
NOT_IN_EMPTY];
REWRITE_TAC[
FINREC] THEN MESON_TAC[
NOT_IN_EMPTY];
IMP_RES_THEN ASSUME_TAC
FINREC_SUC_LEMMA THEN REPEAT GEN_TAC THEN
DISCH_THEN(fun th -> MP_TAC(CONJUNCT1 th) THEN MP_TAC th) THEN
DISCH_THEN(CONJUNCTS_THEN (ANTE_RES_THEN ASSUME_TAC)) THEN
REWRITE_TAC[
FINREC] THEN STRIP_TAC THEN ASM_MESON_TAC[]]);;
let FINREC_FUN_LEMMA = prove
(`!P (R:A->B->C->bool).
(!s. P s ==> ?a n. R s a n) /\
(!n1 n2 s a1 a2. R s a1 n1 /\ R s a2 n2 ==> (a1 = a2) /\ (n1 = n2))
==> ?f. !s a. P s ==> ((?n. R s a n) <=> (f s = a))`,
REPEAT STRIP_TAC THEN EXISTS_TAC `\s:A. @a:B. ?n:C. R s a n` THEN
REPEAT STRIP_TAC THEN BETA_TAC THEN EQ_TAC THENL
[STRIP_TAC THEN MATCH_MP_TAC
SELECT_UNIQUE THEN ASM_MESON_TAC[];
DISCH_THEN(SUBST1_TAC o SYM) THEN CONV_TAC SELECT_CONV THEN
ASM_MESON_TAC[]]);;
let FINREC_FUN = prove
(`!(f:A->B->B) b.
(!x y s. ~(x = y) ==> (f x (f y s) = f y (f x s)))
==> ?g. (g {} = b) /\
!s x.
FINITE s /\ x
IN s
==> (g s = f x (g (s
DELETE x)))`,
REPEAT STRIP_TAC THEN IMP_RES_THEN MP_TAC
FINREC_UNIQUE_LEMMA THEN
DISCH_THEN(MP_TAC o SPEC `b:B`) THEN DISCH_THEN
(MP_TAC o CONJ (SPECL [`f:A->B->B`; `b:B`]
FINREC_EXISTS_LEMMA)) THEN
DISCH_THEN(MP_TAC o MATCH_MP
FINREC_FUN_LEMMA) THEN
DISCH_THEN(X_CHOOSE_TAC `g:(A->bool)->B`) THEN
EXISTS_TAC `g:(A->bool)->B` THEN CONJ_TAC THENL
[SUBGOAL_THEN `
FINITE(EMPTY:A->bool)`
(ANTE_RES_THEN (fun th -> GEN_REWRITE_TAC I [GSYM th])) THENL
[REWRITE_TAC[
FINITE_RULES];
EXISTS_TAC `0` THEN REWRITE_TAC[
FINREC]];
REPEAT STRIP_TAC THEN
ANTE_RES_THEN MP_TAC (ASSUME `
FINITE(s:A->bool)`) THEN
DISCH_THEN(ASSUME_TAC o GSYM) THEN ASM_REWRITE_TAC[] THEN
FIRST_ASSUM(MP_TAC o SPEC `(g:(A->bool)->B) s`) THEN
REWRITE_TAC[] THEN REWRITE_TAC[
LEFT_IMP_EXISTS_THM] THEN
INDUCT_TAC THENL
[ASM_REWRITE_TAC[
FINREC] THEN DISCH_TAC THEN UNDISCH_TAC `x:A
IN s` THEN
ASM_REWRITE_TAC[
NOT_IN_EMPTY];
IMP_RES_THEN ASSUME_TAC
FINREC_SUC_LEMMA THEN
DISCH_THEN(ANTE_RES_THEN (MP_TAC o SPEC `x:A`)) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `w:B` (CONJUNCTS_THEN ASSUME_TAC)) THEN
SUBGOAL_THEN `(g (s
DELETE x:A) = w:B)` SUBST1_TAC THENL
[SUBGOAL_THEN `
FINITE(s
DELETE x:A)` MP_TAC THENL
[MATCH_MP_TAC
FINITE_SUBSET THEN EXISTS_TAC `s:A->bool` THEN
ASM_REWRITE_TAC[] THEN SET_TAC[];
DISCH_THEN(ANTE_RES_THEN (MP_TAC o GSYM)) THEN
DISCH_THEN(fun th -> REWRITE_TAC[th]) THEN
EXISTS_TAC `n:num` THEN ASM_REWRITE_TAC[]];
ASM_REWRITE_TAC[]]]]);;
let SET_RECURSION_LEMMA = prove
(`!(f:A->B->B) b.
(!x y s. ~(x = y) ==> (f x (f y s) = f y (f x s)))
==> ?g. (g {} = b) /\
!x s.
FINITE s
==> (g (x
INSERT s) =
if x
IN s then g s else f x (g s))`,
REPEAT GEN_TAC THEN
DISCH_THEN(MP_TAC o SPEC `b:B` o MATCH_MP
FINREC_FUN) THEN
DISCH_THEN(X_CHOOSE_THEN `g:(A->bool)->B` STRIP_ASSUME_TAC) THEN
EXISTS_TAC `g:(A->bool)->B` THEN ASM_REWRITE_TAC[] THEN
REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
DISCH_TAC THENL
[AP_TERM_TAC THEN REWRITE_TAC[GSYM
ABSORPTION] THEN ASM_REWRITE_TAC[];
SUBGOAL_THEN `
FINITE(x:A
INSERT s) /\ x
IN (x
INSERT s)` MP_TAC THENL
[REWRITE_TAC[
IN_INSERT] THEN ASM_MESON_TAC[
FINITE_RULES];
DISCH_THEN(ANTE_RES_THEN SUBST1_TAC) THEN
REPEAT AP_TERM_TAC THEN UNDISCH_TAC `~(x:A
IN s)` THEN SET_TAC[]]]);;
let ITSET = new_definition
`ITSET f s b =
(@g. (g {} = b) /\
!x s. FINITE s
==> (g (x INSERT s) = if x IN s then g s else f x (g s)))
s`;;
let FINITE_RECURSION_DELETE = prove
(`!(f:A->B->B) b.
(!x y s. ~(x = y) ==> (f x (f y s) = f y (f x s)))
==> (
ITSET f {} b = b) /\
!x s.
FINITE s
==> (
ITSET f s b =
if x
IN s then f x (
ITSET f (s
DELETE x) b)
else
ITSET f (s
DELETE x) b)`,
REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP
FINITE_RECURSION) THEN
DISCH_THEN(STRIP_ASSUME_TAC o SPEC `b:B`) THEN ASM_REWRITE_TAC[] THEN
REPEAT GEN_TAC THEN ASM_CASES_TAC `x:A
IN s` THEN ASM_REWRITE_TAC[] THENL
[DISCH_THEN(MP_TAC o MATCH_MP
FINITE_DELETE_IMP) THEN
DISCH_THEN(ANTE_RES_THEN MP_TAC o SPEC `x:A`) THEN
DISCH_THEN(MP_TAC o SPEC `x:A`) THEN
REWRITE_TAC[
IN_DELETE] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
AP_THM_TAC THEN AP_TERM_TAC THEN UNDISCH_TAC `x:A
IN s` THEN SET_TAC[];
DISCH_TAC THEN AP_THM_TAC THEN AP_TERM_TAC THEN
UNDISCH_TAC `~(x:A
IN s)` THEN SET_TAC[]]);;
let ITSET_EQ = prove
(`!s f g b.
FINITE(s) /\ (!x. x
IN s ==> (f x = g x)) /\
(!x y s. ~(x = y) ==> (f x (f y s) = f y (f x s))) /\
(!x y s. ~(x = y) ==> (g x (g y s) = g y (g x s)))
==> (
ITSET f s b =
ITSET g s b)`,
(* ------------------------------------------------------------------------- *)
(* Cardinality. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* A stronger still form of induction where we get to choose the element. *)
(* ------------------------------------------------------------------------- *)
let FINITE_INDUCT_DELETE = prove
(`!P. P {} /\
(!s.
FINITE s /\ ~(s = {}) ==> ?x. x
IN s /\ (P(s
DELETE x) ==> P s))
==> !s:A->bool.
FINITE s ==> P s`,
GEN_TAC THEN STRIP_TAC THEN GEN_TAC THEN WF_INDUCT_TAC `
CARD(s:A->bool)` THEN
ASM_CASES_TAC `s:A->bool = {}` THEN ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
UNDISCH_TAC
`!s.
FINITE s /\ ~(s = {}) ==> ?x:A. x
IN s /\ (P(s
DELETE x) ==> P s)` THEN
DISCH_THEN(MP_TAC o SPEC `s:A->bool`) THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `x:A` (CONJUNCTS_THEN2 ASSUME_TAC MATCH_MP_TAC)) THEN
FIRST_X_ASSUM(MP_TAC o SPEC `s
DELETE (x:A)`) THEN
ASM_SIMP_TAC[
FINITE_DELETE;
CARD_DELETE;
CARD_EQ_0;
ARITH_RULE `n - 1 < n <=> ~(n = 0)`]);;
(* ------------------------------------------------------------------------- *)
(* Relational form is often more useful. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* This is often more useful as a rewrite. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Produce an explicit expansion for "s HAS_SIZE n" for numeral n. *)
(* ------------------------------------------------------------------------- *)
let HAS_SIZE_CONV =
let pth = prove
(`(~(a
IN {}) /\ P <=> P) /\
(~(a
IN {b}) /\ P <=> ~(a = b) /\ P) /\
(~(a
IN (b
INSERT cs)) /\ P <=> ~(a = b) /\ ~(a
IN cs) /\ P)`,
SET_TAC[])
and qth =
prove
(`((?s. s
HAS_SIZE 0 /\ P s) <=> P {}) /\
((?s. s
HAS_SIZE (SUC n) /\ P s) <=>
(?a s. s
HAS_SIZE n /\ ~(a
IN s) /\ P(a
INSERT s)))`,
REWRITE_TAC[
HAS_SIZE_CLAUSES] THEN MESON_TAC[]) in
let qconv_0 = GEN_REWRITE_CONV I [CONJUNCT1 qth]
and qconv_1 = GEN_REWRITE_CONV I [CONJUNCT2 qth]
and rconv_0 = GEN_REWRITE_CONV I [CONJUNCT1 pth]
and rconv_1 = GEN_REWRITE_CONV I [CONJUNCT2 pth] in
let rec EXISTS_HAS_SIZE_AND_CONV tm =
(qconv_0 ORELSEC
(BINDER_CONV(LAND_CONV(RAND_CONV num_CONV)) THENC
qconv_1 THENC
BINDER_CONV EXISTS_HAS_SIZE_AND_CONV)) tm in
let rec NOT_IN_INSERT_CONV tm =
((rconv_0 THENC NOT_IN_INSERT_CONV) ORELSEC
(rconv_1 THENC RAND_CONV NOT_IN_INSERT_CONV) ORELSEC
ALL_CONV) tm in
let HAS_SIZE_CONV =
GEN_REWRITE_CONV I [CONJUNCT1
HAS_SIZE_CLAUSES] ORELSEC
(RAND_CONV num_CONV THENC
GEN_REWRITE_CONV I [CONJUNCT2
HAS_SIZE_CLAUSES] THENC
BINDER_CONV EXISTS_HAS_SIZE_AND_CONV) in
fun tm ->
let th = HAS_SIZE_CONV tm in
let tm' = rand(concl th) in
let evs,bod = strip_exists tm' in
if evs = [] then th else
let th' = funpow (length evs) BINDER_CONV NOT_IN_INSERT_CONV tm' in
TRANS th th';
;
(* ------------------------------------------------------------------------- *)
(* Various useful lemmas about cardinalities of unions etc. *)
(* ------------------------------------------------------------------------- *)
let CARD_SUBSET_EQ = prove
(`!(a:A->bool) b.
FINITE b /\ a
SUBSET b /\ (
CARD a =
CARD b) ==> (a = b)`,
REPEAT STRIP_TAC THEN
MP_TAC(SPECL [`a:A->bool`; `b
DIFF (a:A->bool)`]
CARD_UNION) THEN
SUBGOAL_THEN `
FINITE(a:A->bool)` ASSUME_TAC THENL
[ASM_MESON_TAC[
FINITE_SUBSET]; ALL_TAC] THEN
SUBGOAL_THEN `
FINITE(b:A->bool
DIFF a)` ASSUME_TAC THENL
[MATCH_MP_TAC
FINITE_SUBSET THEN EXISTS_TAC `b:A->bool` THEN
ASM_REWRITE_TAC[] THEN SET_TAC[]; ALL_TAC] THEN
SUBGOAL_THEN `a:A->bool
INTER (b
DIFF a) =
EMPTY` ASSUME_TAC THENL
[SET_TAC[]; ALL_TAC] THEN
ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN `a
UNION (b:A->bool
DIFF a) = b` ASSUME_TAC THENL
[UNDISCH_TAC `a:A->bool
SUBSET b` THEN SET_TAC[]; ALL_TAC] THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE `(a = a + b) <=> (b = 0)`] THEN DISCH_TAC THEN
SUBGOAL_THEN `b:A->bool
DIFF a =
EMPTY` MP_TAC THENL
[REWRITE_TAC[GSYM
HAS_SIZE_0] THEN
ASM_REWRITE_TAC[
HAS_SIZE];
UNDISCH_TAC `a:A->bool
SUBSET b` THEN SET_TAC[]]);;
let CARD_SUBSET = prove
(`!(a:A->bool) b. a
SUBSET b /\
FINITE(b) ==>
CARD(a) <=
CARD(b)`,
REPEAT STRIP_TAC THEN
SUBGOAL_THEN `b:A->bool = a
UNION (b
DIFF a)` SUBST1_TAC THENL
[UNDISCH_TAC `a:A->bool
SUBSET b` THEN SET_TAC[]; ALL_TAC] THEN
SUBGOAL_THEN
`
CARD (a
UNION b
DIFF a) =
CARD(a:A->bool) +
CARD(b
DIFF a)`
SUBST1_TAC THENL
[MATCH_MP_TAC
CARD_UNION THEN REPEAT CONJ_TAC THENL
[MATCH_MP_TAC
FINITE_SUBSET THEN EXISTS_TAC `b:A->bool` THEN
ASM_REWRITE_TAC[];
MATCH_MP_TAC
FINITE_SUBSET THEN EXISTS_TAC `b:A->bool` THEN
ASM_REWRITE_TAC[] THEN SET_TAC[];
SET_TAC[]];
ARITH_TAC]);;
(* ------------------------------------------------------------------------- *)
(* Cardinality of image under maps, injective or general. *)
(* ------------------------------------------------------------------------- *)
let CARD_IMAGE_EQ_INJ = prove
(`!f:A->B s.
FINITE s
==> (
CARD(
IMAGE f s) =
CARD s <=>
!x y. x
IN s /\ y
IN s /\ f x = f y ==> x = y)`,
REPEAT STRIP_TAC THEN EQ_TAC THENL
[DISCH_TAC; ASM_MESON_TAC[
CARD_IMAGE_INJ]] THEN
MAP_EVERY X_GEN_TAC [`x:A`; `y:A`] THEN STRIP_TAC THEN
ASM_CASES_TAC `x:A = y` THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `
CARD(
IMAGE (f:A->B) s) =
CARD s` THEN
SUBGOAL_THEN `
IMAGE (f:A->B) s =
IMAGE f (s
DELETE y)` SUBST1_TAC THENL
[ASM SET_TAC[]; REWRITE_TAC[]] THEN
MATCH_MP_TAC(ARITH_RULE `!n. m <= n /\ n < p ==> ~(m:num = p)`) THEN
EXISTS_TAC `
CARD(s
DELETE (y:A))` THEN
ASM_SIMP_TAC[
CARD_IMAGE_LE;
FINITE_DELETE] THEN
ASM_SIMP_TAC[
CARD_DELETE;
CARD_EQ_0;
ARITH_RULE `n - 1 < n <=> ~(n = 0)`] THEN
ASM SET_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Choosing a smaller subset of a given size. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Cardinality of product. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Actually introduce a Cartesian product operation. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("CROSS",(22,"right"));;
(* ------------------------------------------------------------------------- *)
(* Cardinality of functions with bounded domain (support) and range. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Cardinality of type bool. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Hence cardinality of powerset. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Set of numbers is infinite. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Set of strings is infinite. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Non-trivial intervals of reals are infinite. *)
(* ------------------------------------------------------------------------- *)
let FINITE_REAL_INTERVAL = prove
(`(!a. ~FINITE {x:real | a < x}) /\
(!a. ~FINITE {x:real | a <= x}) /\
(!b. ~FINITE {x:real | x < b}) /\
(!b. ~FINITE {x:real | x <= b}) /\
(!a b.
FINITE {x:real | a < x /\ x < b} <=> b <= a) /\
(!a b.
FINITE {x:real | a <= x /\ x < b} <=> b <= a) /\
(!a b.
FINITE {x:real | a < x /\ x <= b} <=> b <= a) /\
(!a b.
FINITE {x:real | a <= x /\ x <= b} <=> b <= a)`,
SUBGOAL_THEN `!a b.
FINITE {x:real | a < x /\ x < b} <=> b <= a`
ASSUME_TAC THENL
[REPEAT GEN_TAC THEN REWRITE_TAC[GSYM
REAL_NOT_LT] THEN
ASM_CASES_TAC `a:real < b` THEN
ASM_SIMP_TAC[REAL_ARITH `~(a:real < b) ==> ~(a < x /\ x < b)`] THEN
REWRITE_TAC[
EMPTY_GSPEC;
FINITE_EMPTY] THEN
DISCH_THEN(MP_TAC o MATCH_MP (REWRITE_RULE[
IMP_CONJ]
FINITE_SUBSET)) THEN
DISCH_THEN(MP_TAC o SPEC `
IMAGE (\n. a + (b - a) / (&n + &2)) (:num)`) THEN
REWRITE_TAC[
SUBSET;
FORALL_IN_IMAGE;
IN_UNIV;
IN_ELIM_THM] THEN
SIMP_TAC[
REAL_LT_ADDR; REAL_ARITH `a + x / y < b <=> x / y < b - a`] THEN
ASM_SIMP_TAC[
REAL_LT_DIV;
REAL_SUB_LT;
REAL_LT_LDIV_EQ; NOT_IMP;
REAL_ARITH `&0:real < &n + &2`] THEN
REWRITE_TAC[REAL_ARITH `x:real < x * (n + &2) <=> &0 < x * (n + &1)`] THEN
ASM_SIMP_TAC[
REAL_SUB_LT;
REAL_LT_MUL; REAL_ARITH `&0:real < &n + &1`] THEN
MP_TAC
num_INFINITE THEN REWRITE_TAC[
INFINITE] THEN
MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN CONV_TAC SYM_CONV THEN
MATCH_MP_TAC
FINITE_IMAGE_INJ_EQ THEN
ASM_SIMP_TAC[REAL_OF_NUM_EQ; REAL_FIELD
`a < b ==> (a + (b - a) / (&n + &2) = a + (b - a) / (&m + &2) <=>
&n:real = &m)`];
ALL_TAC] THEN
ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THEN REPEAT GEN_TAC THENL
[DISCH_THEN(MP_TAC o SPEC `{x:real | a < x /\ x < a + &1}` o
MATCH_MP(REWRITE_RULE[
IMP_CONJ]
FINITE_SUBSET)) THEN
ASM_REWRITE_TAC[
SUBSET;
IN_ELIM_THM] THEN REAL_ARITH_TAC;
DISCH_THEN(MP_TAC o SPEC `{x:real | a < x /\ x < a + &1}` o
MATCH_MP(REWRITE_RULE[
IMP_CONJ]
FINITE_SUBSET)) THEN
ASM_REWRITE_TAC[
SUBSET;
IN_ELIM_THM] THEN REAL_ARITH_TAC;
DISCH_THEN(MP_TAC o SPEC `{x:real | b - &1 < x /\ x < b}` o
MATCH_MP(REWRITE_RULE[
IMP_CONJ]
FINITE_SUBSET)) THEN
ASM_REWRITE_TAC[
SUBSET;
IN_ELIM_THM] THEN REAL_ARITH_TAC;
DISCH_THEN(MP_TAC o SPEC `{x:real | b - &1 < x /\ x < b}` o
MATCH_MP(REWRITE_RULE[
IMP_CONJ]
FINITE_SUBSET)) THEN
ASM_REWRITE_TAC[
SUBSET;
IN_ELIM_THM] THEN REAL_ARITH_TAC;
REWRITE_TAC[REAL_ARITH
`a:real <= x /\ x < b <=> (a < x /\ x < b) \/ ~(b <= a) /\ x = a`];
REWRITE_TAC[REAL_ARITH
`a:real < x /\ x <= b <=> (a < x /\ x < b) \/ ~(b <= a) /\ x = b`];
ASM_CASES_TAC `b:real = a` THEN
ASM_SIMP_TAC[REAL_LE_ANTISYM;
REAL_LE_REFL;
SING_GSPEC;
FINITE_SING] THEN
ASM_SIMP_TAC[REAL_ARITH
`~(b:real = a) ==>
(a <= x /\ x <= b <=> (a < x /\ x < b) \/ ~(b <= a) /\ x = a \/
~(b <= a) /\ x = b)`]] THEN
ASM_REWRITE_TAC[
FINITE_UNION; SET_RULE
`{x | p x \/ q x} = {x | p x}
UNION {x | q x}`] THEN
ASM_CASES_TAC `b:real <= a` THEN
ASM_REWRITE_TAC[
EMPTY_GSPEC;
FINITE_EMPTY]);;
(* ------------------------------------------------------------------------- *)
(* Indexing of finite sets and enumeration of subsets of N in order. *)
(* ------------------------------------------------------------------------- *)
let HAS_SIZE_INDEX = prove
(`!s n. s
HAS_SIZE n
==> ?f:num->A. (!m. m < n ==> f(m)
IN s) /\
(!x. x
IN s ==> ?!m. m < n /\ (f m = x))`,
ONCE_REWRITE_TAC[
SWAP_FORALL_THM] THEN INDUCT_TAC THEN
SIMP_TAC[
HAS_SIZE_0;
HAS_SIZE_SUC;
LT;
NOT_IN_EMPTY] THEN
X_GEN_TAC `s:A->bool` THEN REWRITE_TAC[
EXTENSION;
NOT_IN_EMPTY] THEN
REWRITE_TAC[
NOT_FORALL_THM] THEN
DISCH_THEN(CONJUNCTS_THEN2 (X_CHOOSE_TAC `a:A`) (MP_TAC o SPEC `a:A`)) THEN
ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
FIRST_X_ASSUM(MP_TAC o SPEC `s
DELETE (a:A)`) THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `f:num->A` STRIP_ASSUME_TAC) THEN
EXISTS_TAC `\m:num. if m < n then f(m) else a:A` THEN CONJ_TAC THENL
[GEN_TAC THEN REWRITE_TAC[] THEN COND_CASES_TAC THEN
ASM_MESON_TAC[
IN_DELETE]; ALL_TAC] THEN
X_GEN_TAC `x:A` THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
FIRST_X_ASSUM(MP_TAC o SPEC `x:A`) THEN
ASM_REWRITE_TAC[
IN_DELETE] THEN
CONV_TAC(ONCE_DEPTH_CONV COND_ELIM_CONV) THEN
ASM_CASES_TAC `a:A = x` THEN ASM_SIMP_TAC[] THEN
ASM_MESON_TAC[
LT_REFL;
IN_DELETE]);;
let INFINITE_ENUMERATE = prove
(`!s:num->bool.
INFINITE s
==> ?r:num->num. (!m n. m < n ==> r(m) < r(n)) /\
IMAGE r (:num) = s`,
REPEAT STRIP_TAC THEN
SUBGOAL_THEN `!n:num. ?x. n <= x /\ x
IN s` MP_TAC THENL
[ASM_MESON_TAC[
INFINITE;
num_FINITE;
LT_IMP_LE;
NOT_LE];
GEN_REWRITE_TAC (LAND_CONV o BINDER_CONV) [
num_WOP]] THEN
REWRITE_TAC[
SKOLEM_THM;
LEFT_IMP_EXISTS_THM;
FORALL_AND_THM] THEN
REWRITE_TAC[TAUT `p ==> ~(q /\ r) <=> q /\ p ==> ~r`] THEN
X_GEN_TAC `next:num->num` THEN STRIP_TAC THEN
(MP_TAC o prove_recursive_functions_exist num_RECURSION)
`(f(0) = next 0) /\ (!n. f(SUC n) = next(f n + 1))` THEN
MATCH_MP_TAC
MONO_EXISTS THEN X_GEN_TAC `r:num->num` THEN STRIP_TAC THEN
MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
[GEN_TAC THEN INDUCT_TAC THEN ASM_REWRITE_TAC[
LT] THEN
ASM_MESON_TAC[ARITH_RULE `m <= n /\ n + 1 <= p ==> m < p`;
LE_LT];
DISCH_TAC] THEN
ASM_REWRITE_TAC[GSYM
SUBSET_ANTISYM_EQ;
FORALL_IN_IMAGE;
SUBSET] THEN
REWRITE_TAC[
IN_IMAGE;
IN_UNIV] THEN CONJ_TAC THENL
[INDUCT_TAC THEN ASM_MESON_TAC[]; ALL_TAC] THEN
MATCH_MP_TAC
num_WF THEN X_GEN_TAC `n:num` THEN REPEAT STRIP_TAC THEN
ASM_CASES_TAC `?m:num. m < n /\ m
IN s` THENL
[MP_TAC(SPEC `\m:num. m < n /\ m
IN s`
num_MAX) THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC(TAUT
`p /\ (q ==> r) ==> (p <=> q) ==> r`) THEN
CONJ_TAC THENL [MESON_TAC[
LT_IMP_LE]; ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `p:num` STRIP_ASSUME_TAC) THEN
SUBGOAL_THEN `?q. p = (r:num->num) q` (CHOOSE_THEN SUBST_ALL_TAC) THENL
[ASM_MESON_TAC[]; EXISTS_TAC `SUC q`] THEN
ASM_REWRITE_TAC[GSYM
LE_ANTISYM; GSYM
NOT_LT] THEN
ASM_MESON_TAC[
NOT_LE; ARITH_RULE `r < p <=> r + 1 <= p`];
EXISTS_TAC `0` THEN ASM_REWRITE_TAC[GSYM
LE_ANTISYM; GSYM
NOT_LT] THEN
ASM_MESON_TAC[
LE_0]]);;
(* ------------------------------------------------------------------------- *)
(* Mapping between finite sets and lists. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Mappings from finite set enumerations to lists (no "setification"). *)
(* ------------------------------------------------------------------------- *)
let dest_setenum =
let fn = splitlist (dest_binary "INSERT") in
fun tm -> let l,n = fn tm in
if is_const n & fst(dest_const n) = "EMPTY" then l
else failwith "dest_setenum: not a finite set enumeration";;
let is_setenum = can dest_setenum;;
let mk_setenum =
let insert_atm = `(INSERT):A->(A->bool)->(A->bool)`
and nil_atm = `(EMPTY):A->bool` in
fun (l,ty) ->
let insert_tm = inst [ty,aty] insert_atm
and nil_tm = inst [ty,aty] nil_atm in
itlist (mk_binop insert_tm) l nil_tm;;
let mk_fset l = mk_setenum(l,type_of(hd l));;
(* ------------------------------------------------------------------------- *)
(* Pairwise property over sets and lists. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Some additional properties of "set_of_list". *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Classic result on function of finite set into itself. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Converse relation between cardinality and injection. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Occasionally handy rewrites. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Injectivity and surjectivity of image under a function. *)
(* ------------------------------------------------------------------------- *)
let INJECTIVE_ON_IMAGE = prove
(`!f:A->B u.
(!s t. s
SUBSET u /\ t
SUBSET u /\
IMAGE f s =
IMAGE f t ==> s = t) <=>
(!x y. x
IN u /\ y
IN u /\ f x = f y ==> x = y)`,
REPEAT GEN_TAC THEN EQ_TAC THENL [DISCH_TAC; SET_TAC[]] THEN
MAP_EVERY X_GEN_TAC [`x:A`; `y:A`] THEN STRIP_TAC THEN
FIRST_X_ASSUM(MP_TAC o SPECL [`{x:A}`; `{y:A}`]) THEN
ASM_REWRITE_TAC[
SING_SUBSET;
IMAGE_CLAUSES] THEN SET_TAC[]);;
let SURJECTIVE_ON_IMAGE = prove
(`!f:A->B u v.
(!t. t
SUBSET v ==> ?s. s
SUBSET u /\
IMAGE f s = t) <=>
(!y. y
IN v ==> ?x. x
IN u /\ f x = y)`,
REPEAT GEN_TAC THEN EQ_TAC THENL
[DISCH_TAC THEN X_GEN_TAC `y:B` THEN DISCH_TAC THEN
FIRST_X_ASSUM(MP_TAC o SPEC `{y:B}`) THEN ASM SET_TAC[];
DISCH_TAC THEN X_GEN_TAC `t:B->bool` THEN DISCH_TAC THEN
EXISTS_TAC `{x | x
IN u /\ (f:A->B) x
IN t}` THEN ASM SET_TAC[]]);;
(* ------------------------------------------------------------------------- *)
(* Existence of bijections between two finite sets of same size. *)
(* ------------------------------------------------------------------------- *)
let BIJECTIONS_HAS_SIZE_EQ = prove
(`!s t f:A->B g.
(!x. x
IN s ==> f(x)
IN t /\ g(f x) = x) /\
(!y. y
IN t ==> g(y)
IN s /\ f(g y) = y)
==> !n. s
HAS_SIZE n <=> t
HAS_SIZE n`,
REPEAT STRIP_TAC THEN EQ_TAC THEN
MATCH_MP_TAC(ONCE_REWRITE_RULE
[TAUT `a /\ b /\ c ==> d <=> a /\ b ==> c ==> d`]
BIJECTIONS_HAS_SIZE) THENL
[MAP_EVERY EXISTS_TAC [`f:A->B`; `g:B->A`];
MAP_EVERY EXISTS_TAC [`g:B->A`; `f:A->B`]] THEN
ASM_MESON_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Transitive relation with finitely many predecessors is wellfounded. *)
(* ------------------------------------------------------------------------- *)
let WF_FINITE = prove
(`!(<<). (!x. ~(x << x)) /\ (!x y z. x << y /\ y << z ==> x << z) /\
(!x:A.
FINITE {y | y << x})
==>
WF(<<)`,
(* ------------------------------------------------------------------------- *)
(* Cardinal comparisons (more theory in Examples/card.ml) *)
(* ------------------------------------------------------------------------- *)
let le_c = new_definition
`s <=_c t <=> ?f. (!x. x IN s ==> f(x) IN t) /\
(!x y. x IN s /\ y IN s /\ (f(x) = f(y)) ==> (x = y))`;;
let lt_c = new_definition
`s <_c t <=> s <=_c t /\ ~(t <=_c s)`;;
let eq_c = new_definition
`s =_c t <=> ?f. (!x. x IN s ==> f(x) IN t) /\
!y. y IN t ==> ?!x. x IN s /\ (f x = y)`;;
let ge_c = new_definition
`s >=_c t <=> t <=_c s`;;
let gt_c = new_definition
`s >_c t <=> t <_c s`;;
let LE_C = prove
(`!s t. s <=_c t <=> ?g. !x. x
IN s ==> ?y. y
IN t /\ (g y = x)`,
let GE_C = prove
(`!s t. s >=_c t <=> ?f. !y. y
IN t ==> ?x. x
IN s /\ (y = f x)`,
REWRITE_TAC[
ge_c;
LE_C] THEN MESON_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Supremum and infimum. *)
(* ------------------------------------------------------------------------- *)
let SUP_EQ = prove
(`!s t. (!b. (!x. x
IN s ==> x <= b) <=> (!x. x
IN t ==> x <= b))
==> sup s = sup t`,
SIMP_TAC[sup]);;
let SUP = prove
(`!s. ~(s = {}) /\ (?b. !x. x
IN s ==> x <= b)
==> (!x. x
IN s ==> x <= sup s) /\
!b. (!x. x
IN s ==> x <= b) ==> sup s <= b`,
REWRITE_TAC[sup] THEN CONV_TAC(ONCE_DEPTH_CONV SELECT_CONV) THEN
REPEAT STRIP_TAC THEN MATCH_MP_TAC
REAL_COMPLETE THEN
ASM_MESON_TAC[
MEMBER_NOT_EMPTY]);;
let REAL_SUP_BOUNDS = prove
(`!s a b. ~(s = {}) /\ (!x. x
IN s ==> a <= x /\ x <= b)
==> a <= sup s /\ sup s <= b`,
REPEAT GEN_TAC THEN STRIP_TAC THEN
MP_TAC(SPEC `s:real->bool`
SUP) THEN ANTS_TAC THENL
[ASM_MESON_TAC[]; ALL_TAC] THEN
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM
MEMBER_NOT_EMPTY]) THEN
ASM_MESON_TAC[
REAL_LE_TRANS]);;
let REAL_SUP_ASCLOSE = prove
(`!s l e. ~(s = {}) /\ (!x. x
IN s ==> abs(x - l) <= e)
==> abs(sup s - l) <= e`,
SIMP_TAC[REAL_ARITH `abs(x - l):real <= e <=> l - e <= x /\ x <= l + e`] THEN
REWRITE_TAC[
REAL_SUP_BOUNDS]);;
let INF_EQ = prove
(`!s t. (!a. (!x. x
IN s ==> a <= x) <=> (!x. x
IN t ==> a <= x))
==> inf s = inf t`,
SIMP_TAC[inf]);;
let INF = prove
(`!s. ~(s = {}) /\ (?b. !x. x
IN s ==> b <= x)
==> (!x. x
IN s ==> inf s <= x) /\
!b. (!x. x
IN s ==> b <= x) ==> b <= inf s`,
let REAL_INF_BOUNDS = prove
(`!s a b. ~(s = {}) /\ (!x. x
IN s ==> a <= x /\ x <= b)
==> a <= inf s /\ inf s <= b`,
REPEAT GEN_TAC THEN STRIP_TAC THEN
MP_TAC(SPEC `s:real->bool`
INF) THEN ANTS_TAC THENL
[ASM_MESON_TAC[]; ALL_TAC] THEN
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM
MEMBER_NOT_EMPTY]) THEN
ASM_MESON_TAC[
REAL_LE_TRANS]);;
let REAL_INF_ASCLOSE = prove
(`!s l e. ~(s = {}) /\ (!x. x
IN s ==> abs(x - l) <= e)
==> abs(inf s - l) <= e`,
SIMP_TAC[REAL_ARITH `abs(x - l):real <= e <=> l - e <= x /\ x <= l + e`] THEN
REWRITE_TAC[
REAL_INF_BOUNDS]);;
let SUP_UNIQUE = prove
(`!s b. (!c. (!x. x
IN s ==> x <= c) <=> b <= c) ==> sup s = b`,
REPEAT STRIP_TAC THEN GEN_REWRITE_TAC RAND_CONV [GSYM
SUP_SING] THEN
MATCH_MP_TAC
SUP_EQ THEN ASM SET_TAC[]);;
let INF_UNIQUE = prove
(`!s b. (!c. (!x. x
IN s ==> c <= x) <=> c <= b) ==> inf s = b`,
REPEAT STRIP_TAC THEN GEN_REWRITE_TAC RAND_CONV [GSYM
INF_SING] THEN
MATCH_MP_TAC
INF_EQ THEN ASM SET_TAC[]);;
let SUP_UNION = prove
(`!s t. ~(s = {}) /\ ~(t = {}) /\
(?b. !x. x
IN s ==> x <= b) /\ (?c. !x. x
IN t ==> x <= c)
==> sup(s
UNION t) = max (sup s) (sup t)`,
let INF_UNION = prove
(`!s t. ~(s = {}) /\ ~(t = {}) /\
(?b. !x. x
IN s ==> b <= x) /\ (?c. !x. x
IN t ==> c <= x)
==> inf(s
UNION t) = min (inf s) (inf t)`,
(* ------------------------------------------------------------------------- *)
(* Inductive definition of sets, by reducing them to inductive relations. *)
(* ------------------------------------------------------------------------- *)
let new_inductive_set =
let const_of_var v = mk_mconst(name_of v,type_of v) in
let comb_all =
let rec f (n:int) (tm:term) : hol_type list -> term = function
| [] -> tm
| ty::tys ->
let v = variant (variables tm) (mk_var("x"^string_of_int n,ty)) in
f (n+1) (mk_comb(tm,v)) tys in
fun tm -> let tys = fst (splitlist dest_fun_ty (type_of tm)) in
f 0 tm tys in
let mk_eqin = REWR_CONV (GSYM IN) o comb_all in
let transf conv = rhs o concl o conv in
let remove_in_conv ptm : conv =
let rconv = REWR_CONV(SYM(mk_eqin ptm)) in
fun tm -> let htm = fst(strip_comb(snd(dest_binary "IN" tm))) in
if htm = ptm then rconv tm else fail() in
let remove_in_transf =
transf o ONCE_DEPTH_CONV o FIRST_CONV o map remove_in_conv in
let rule_head tm =
let tm = snd(strip_forall tm) in
let tm = snd(splitlist(dest_binop `(==>)`) tm) in
let tm = snd(dest_binary "IN" tm) in
fst(strip_comb tm) in
let find_pvars = setify o map rule_head o binops `(/\)` in
fun tm ->
let pvars = find_pvars tm in
let dtm = remove_in_transf pvars tm in
let th_rules, th_induct, th_cases = new_inductive_definition dtm in
let insert_in_rule = REWRITE_RULE(map (mk_eqin o const_of_var) pvars) in
insert_in_rule th_rules,
insert_in_rule th_induct,
insert_in_rule th_cases;;