needs "../formal_lp/hypermap/list_hypermap_defs.hl";;
open Sphere;;
(* For IMAGE_LEMMA *)
open Hypermap_and_fan;;
let REMOVE_ASSUM = POP_ASSUM (fun th -> ALL_TAC);;
(****************************)
(* INDEX *)
let EL_INDEX = prove(`!(x:A) list.
MEM x list ==>
EL (
INDEX x list) list = x`,
GEN_TAC THEN LIST_INDUCT_TAC THEN REWRITE_TAC[
MEM] THEN
ASM_CASES_TAC `x = h:A` THEN ASM_REWRITE_TAC[] THENL
[
ASM_REWRITE_TAC[
INDEX;
EL;
HD];
ALL_TAC
] THEN
ASM_REWRITE_TAC[
INDEX;
EL;
TL]);;
(* ALL_DISTINCT *)
(* list_sum *)
(* Shift left/right *)
let EL_SHIFT_RIGHT = prove(`!i (list:(A)list). i <
LENGTH list ==>
EL i (
shift_right list) = if (i = 0) then
EL (
LENGTH list - 1) list else
EL (i - 1) list`,
REPEAT STRIP_TAC THEN
ASM_CASES_TAC `i = 0` THEN ASM_REWRITE_TAC[] THENL
[
SUBGOAL_THEN `~(list:(A)list = [])` ASSUME_TAC THENL
[
DISCH_TAC THEN UNDISCH_TAC `i <
LENGTH (list:(A)list)` THEN
ASM_REWRITE_TAC[
LENGTH;
LT_REFL];
ALL_TAC
] THEN
ASM_SIMP_TAC[GSYM
LAST_EL] THEN
ASM_REWRITE_TAC[
shift_right;
EL;
HD];
ALL_TAC
] THEN
MP_TAC (CONJUNCT1 (SPEC `list:(A)list`
SHIFT_LEFT_RIGHT)) THEN
DISCH_THEN (MP_TAC o (fun
th -> AP_TERM `(EL:num->(A)list->A) (i - 1)`
th)) THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
MP_TAC (SPECL [`i - 1`; `
shift_right (list:(A)list)`]
EL_SHIFT_LEFT) THEN
REWRITE_TAC[
LENGTH_SHIFT_RIGHT;
SHIFT_LEFT_RIGHT] THEN
ANTS_TAC THENL
[
POP_ASSUM MP_TAC THEN POP_ASSUM MP_TAC THEN ARITH_TAC;
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
SUBGOAL_THEN `~(i - 1 =
LENGTH (list:(A)list) - 1)` (fun
th -> REWRITE_TAC[
th]) THENL
[
POP_ASSUM MP_TAC THEN POP_ASSUM MP_TAC THEN ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[ARITH_RULE `~(i = 0) ==> i - 1 + 1 = i`]);;
(* NEXT_EL, PREV_EL *)
let PREV_NEXT_ID = prove(`!(x:A) list.
ALL_DISTINCT list /\
MEM x list ==>
PREV_EL (
NEXT_EL x list) list = x`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[
NEXT_EL] THEN
SUBGOAL_THEN `~(list = []:(A)list)` ASSUME_TAC THENL
[
DISCH_TAC THEN UNDISCH_TAC `
MEM (x:A) list` THEN
ASM_REWRITE_TAC[
MEM];
ALL_TAC
] THEN
COND_CASES_TAC THENL
[
REWRITE_TAC[
PREV_EL] THEN
ASM_SIMP_TAC[
INDEX_HD;
LAST_EL] THEN
MP_TAC (SPECL [`x:A`; `list:(A)list`]
EL_INDEX) THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
REWRITE_TAC[
PREV_EL] THEN
ABBREV_TAC `i =
INDEX (x:A) list` THEN
SUBGOAL_THEN `i + 1 <
LENGTH (list:(A)list)` ASSUME_TAC THENL
[
REWRITE_TAC[ARITH_RULE `i + 1 < n <=> i < n /\ ~(i = n - 1)`] THEN
ASM_REWRITE_TAC[] THEN
POP_ASSUM (fun
th -> REWRITE_TAC[SYM
th]) THEN
ASM_REWRITE_TAC[GSYM
INDEX_LT_LENGTH];
ALL_TAC
] THEN
MP_TAC (SPECL [`i + 1`; `list:(A)list`]
INDEX_EL) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
REWRITE_TAC[ARITH_RULE `~(i + 1 = 0)`; ARITH_RULE `(i + 1) - 1 = i`] THEN
MP_TAC (SPECL [`x:A`; `list:(A)list`]
EL_INDEX) THEN
ASM_SIMP_TAC[]);;
let NEXT_PREV_ID = prove(`!(x:A) list.
ALL_DISTINCT list /\
MEM x list ==>
NEXT_EL (
PREV_EL x list) list = x`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[
PREV_EL] THEN
SUBGOAL_THEN `~(list = []:(A)list)` ASSUME_TAC THENL
[
DISCH_TAC THEN UNDISCH_TAC `
MEM (x:A) list` THEN
ASM_REWRITE_TAC[
MEM];
ALL_TAC
] THEN
SUBGOAL_THEN `0 <
LENGTH (list:(A)list)` ASSUME_TAC THENL
[
UNDISCH_TAC `~(list = []:(A)list)` THEN
ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
REWRITE_TAC[
NOT_LT;
LE;
LENGTH_EQ_NIL];
ALL_TAC
] THEN
COND_CASES_TAC THENL
[
REWRITE_TAC[
NEXT_EL] THEN
SUBGOAL_THEN `
INDEX (
LAST list) (list:(A)list) =
LENGTH list - 1` ASSUME_TAC THENL
[
ASM_SIMP_TAC[
LAST_EL] THEN
MATCH_MP_TAC
INDEX_EL THEN
ASM_REWRITE_TAC[ARITH_RULE `n - 1 < n <=> 0 < n`];
ALL_TAC
] THEN
ASM_REWRITE_TAC[] THEN
MP_TAC (SPECL [`x:A`; `list:(A)list`]
EL_INDEX) THEN
ASM_REWRITE_TAC[
EL];
ALL_TAC
] THEN
REWRITE_TAC[
NEXT_EL] THEN
ABBREV_TAC `i =
INDEX (x:A) list` THEN
SUBGOAL_THEN `0 < i /\ i - 1 <
LENGTH (list:(A)list)` ASSUME_TAC THENL
[
ASM_REWRITE_TAC[
LT_NZ] THEN
MATCH_MP_TAC (ARITH_RULE `i < n ==> i - 1 < n`) THEN
POP_ASSUM (fun
th -> REWRITE_TAC[SYM
th]) THEN
ASM_REWRITE_TAC[GSYM
INDEX_LT_LENGTH];
ALL_TAC
] THEN
MP_TAC (SPECL [`i - 1`; `list:(A)list`]
INDEX_EL) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
ASM_SIMP_TAC[ARITH_RULE `0 < i /\ 0 < n ==> (i - 1 = n - 1 <=> i = n)`] THEN
ASM_SIMP_TAC[ARITH_RULE `0 < i ==> i - 1 + 1 = i`] THEN
EXPAND_TAC "i" THEN ASM_REWRITE_TAC[GSYM
INDEX_EQ_LENGTH] THEN
MP_TAC (SPECL [`x:A`; `list:(A)list`]
EL_INDEX) THEN
ASM_SIMP_TAC[]);;
(* FLATTEN, REMOVE_DUPLICATES *)
let MEM_FLATTEN = prove(`!(x:A) ll.
MEM x (
FLATTEN ll) <=> ?l.
MEM l ll /\
MEM x l`,
GEN_TAC THEN LIST_INDUCT_TAC THEN REWRITE_TAC[
MEM;
FLATTEN;
ITLIST] THEN
REWRITE_TAC[
MEM_APPEND; GSYM
FLATTEN] THEN
EQ_TAC THENL
[
STRIP_TAC THENL
[
EXISTS_TAC `h:(A)list` THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
POP_ASSUM MP_TAC THEN ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
EXISTS_TAC `l:(A)list` THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
STRIP_TAC THENL
[
UNDISCH_TAC `l = h:(A)list` THEN DISCH_THEN (fun
th -> ASM_REWRITE_TAC[SYM
th]);
ALL_TAC
] THEN
DISJ2_TAC THEN ASM_REWRITE_TAC[] THEN
EXISTS_TAC `l:(A)list` THEN ASM_REWRITE_TAC[]);;
(* lists *)
(* Faces *)
let MEM_FIND_LIST = prove(`!(x:A) ll.
MEM x (
FLATTEN ll) ==>
MEM (
find_list x ll) ll`,
REWRITE_TAC[
MEM_FLATTEN] THEN
GEN_TAC THEN LIST_INDUCT_TAC THEN REWRITE_TAC[
MEM] THEN
STRIP_TAC THENL
[
POP_ASSUM MP_TAC THEN ASM_REWRITE_TAC[
find_list] THEN DISCH_TAC THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
ASM_CASES_TAC `
MEM (x:A) h` THEN ASM_REWRITE_TAC[
find_list] THEN
DISJ2_TAC THEN
FIRST_X_ASSUM MATCH_MP_TAC THEN
EXISTS_TAC `l:(A)list` THEN
ASM_REWRITE_TAC[]);;
let MEM_FIND_LIST_NONEMPTY = prove(`!(x:A) ll.
ALL (\l. ~(l = [])) ll ==>
(
MEM x (
FLATTEN ll) <=>
MEM (
find_list x ll) ll)`,
REWRITE_TAC[GSYM
ALL_MEM] THEN
REPEAT STRIP_TAC THEN
EQ_TAC THENL
[
ASM_REWRITE_TAC[
MEM_FIND_LIST];
ALL_TAC
] THEN
POP_ASSUM MP_TAC THEN SPEC_TAC (`ll:((A)list)list`, `ll:((A)list)list`) THEN
LIST_INDUCT_TAC THEN REWRITE_TAC[
MEM] THEN
DISCH_TAC THEN
FIRST_X_ASSUM (MP_TAC o check(is_imp o concl)) THEN
ANTS_TAC THENL
[
GEN_TAC THEN DISCH_TAC THEN
FIRST_X_ASSUM (MP_TAC o SPEC `x:(A)list`) THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
DISCH_TAC THEN
REWRITE_TAC[
find_list] THEN
SUBGOAL_THEN `!t.
find_list x t = h ==>
MEM (x:A) h` ASSUME_TAC THENL
[
FIRST_X_ASSUM (MP_TAC o SPEC `h:(A)list`) THEN
REWRITE_TAC[] THEN DISCH_TAC THEN
LIST_INDUCT_TAC THEN ASM_REWRITE_TAC[
find_list] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> ASM_REWRITE_TAC[SYM
th]);
ALL_TAC
] THEN
ASM_CASES_TAC `
MEM (x:A) h` THEN ASM_REWRITE_TAC[] THENL
[
REWRITE_TAC[
MEM_FLATTEN;
MEM] THEN
EXISTS_TAC `h:(A)list` THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
STRIP_TAC THENL
[
FIRST_X_ASSUM (MP_TAC o SPEC `t:((A)list)list`) THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
REWRITE_TAC[
FLATTEN;
ITLIST;
MEM_APPEND] THEN
ASM_REWRITE_TAC[GSYM
FLATTEN] THEN
FIRST_X_ASSUM MATCH_MP_TAC THEN
ASM_REWRITE_TAC[]);;
(* Hypermap maps properties *)
(* e_list_ext permutes darts *)
(* f_list_ext permutes darts *)
let ALL_DISTINCT_SHIFT_LEFT = prove(`!list:(A)list.
ALL_DISTINCT list ==>
ALL_DISTINCT (
shift_left list)`,
LIST_INDUCT_TAC THEN REWRITE_TAC[
shift_left] THEN
POP_ASSUM (fun
th -> ALL_TAC) THEN
ASM_REWRITE_TAC[
ALL_DISTINCT] THEN
ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
REWRITE_TAC[
NOT_FORALL_THM; NOT_IMP;
EL_APPEND;
LENGTH_APPEND;
LENGTH;
ARITH_SUC] THEN
STRIP_TAC THEN POP_ASSUM MP_TAC THEN
ABBREV_TAC `m =
LENGTH (t:(A)list)` THEN
ASSUME_TAC (ARITH_RULE `!n. n < m + 1 /\ ~(n < m) ==> n = m`) THEN
REPEAT COND_CASES_TAC THENL
[
DISCH_TAC THEN
MAP_EVERY EXISTS_TAC [`SUC i`; `SUC j`] THEN
ASM_REWRITE_TAC[
LT_SUC;
SUC_INJ;
EL;
TL];
FIRST_X_ASSUM (MP_TAC o SPEC `j:num`) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th;
SUB_REFL]) THEN
REWRITE_TAC[
EL;
HD] THEN DISCH_TAC THEN
MAP_EVERY EXISTS_TAC [`SUC i`; `0`] THEN
ASM_REWRITE_TAC[
LT_SUC;
NOT_SUC;
LT_0;
EL;
TL;
HD];
FIRST_X_ASSUM (MP_TAC o SPEC `i:num`) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th;
SUB_REFL]) THEN
REWRITE_TAC[
EL;
HD] THEN DISCH_TAC THEN
MAP_EVERY EXISTS_TAC [`0`; `SUC j`] THEN
ASM_REWRITE_TAC[
LT_SUC;
NOT_SUC;
LT_0;
EL;
TL;
HD];
UNDISCH_TAC `~(i = j:num)` THEN
FIRST_ASSUM (MP_TAC o SPEC `i:num`) THEN FIRST_X_ASSUM (MP_TAC o SPEC `j:num`) THEN
ASM_SIMP_TAC[]
]);;
let NEXT_EL_LIST_PAIRS = prove(`!(d:A#A) list.
ALL_DISTINCT list /\
MEM d (
list_pairs list) ==>
NEXT_EL d (
list_pairs list) = (
SND d,
NEXT_EL (
SND d) list)`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[
NEXT_EL;
LENGTH_LIST_PAIRS] THEN
MP_TAC (SPEC `list:(A)list`
ALL_DISTINCT_LIST_PAIRS) THEN
ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
ABBREV_TAC `i =
INDEX (d:A#A) (
list_pairs list)` THEN
ABBREV_TAC `n =
LENGTH (list:(A)list)` THEN
SUBGOAL_THEN `i < n:num` ASSUME_TAC THENL
[
EXPAND_TAC "n" THEN EXPAND_TAC "i" THEN
ONCE_REWRITE_TAC[GSYM
LENGTH_LIST_PAIRS] THEN
ASM_REWRITE_TAC[GSYM
INDEX_LT_LENGTH];
ALL_TAC
] THEN
SUBGOAL_THEN `
EL i (
list_pairs list) = d:A#A` ASSUME_TAC THENL
[
EXPAND_TAC "i" THEN
MATCH_MP_TAC
EL_INDEX THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MP_TAC (SPECL [`i:num`; `d:A#A`; `list:(A)list`]
INDEX_FST_SND) THEN
ASM_REWRITE_TAC[] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL
[
STRIP_TAC THEN
ASM_REWRITE_TAC[] THEN
MP_TAC (SPEC_ALL
EL_LIST_PAIRS) THEN
ASM_REWRITE_TAC[] THEN
ANTS_TAC THENL
[
MATCH_MP_TAC (ARITH_RULE `i < n ==> n - 1 < n`) THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
ONCE_REWRITE_TAC[GSYM
EL] THEN
MP_TAC (SPECL [`0`; `list:(A)list`]
EL_LIST_PAIRS) THEN
ASM_REWRITE_TAC[] THEN
ANTS_TAC THENL [ MATCH_MP_TAC (ARITH_RULE `i < n ==> 0 < n`) THEN ASM_REWRITE_TAC[]; ALL_TAC ] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th;
PAIR_EQ]) THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
MP_TAC (SPECL [`i + 1`; `list:(A)list`]
EL_LIST_PAIRS) THEN
SUBGOAL_THEN `i + 1 < n` ASSUME_TAC THENL
[
REPLICATE_TAC 3 (POP_ASSUM MP_TAC) THEN ARITH_TAC;
ALL_TAC
] THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
ONCE_REWRITE_TAC[GSYM
EL] THEN
MP_TAC (SPECL [`i:num`; `list:(A)list`]
EL_LIST_PAIRS) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th;
PAIR_EQ]) THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[
PAIR_EQ]);;
(* e o n o f = I *)
(* hypermap_of_list is a hypermap *)
(* Set of faces *)
let NEXT_EL_MOD = prove(`!list (x:A).
MEM x list ==>
NEXT_EL x list =
EL ((
INDEX x list + 1) MOD
LENGTH list) list`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[
NEXT_EL] THEN
ABBREV_TAC `n =
LENGTH (list:(A)list)` THEN
SUBGOAL_THEN `1 <= n` ASSUME_TAC THENL
[
UNDISCH_TAC `
MEM (x:A) list` THEN
ASM_REWRITE_TAC[
MEM_EXISTS_EL] THEN
STRIP_TAC THEN UNDISCH_TAC `i < n:num` THEN
ARITH_TAC;
ALL_TAC
] THEN
COND_CASES_TAC THENL
[
ASM_SIMP_TAC[ARITH_RULE `1 <= n ==> n - 1 + 1 = n`] THEN
MP_TAC (SPECL [`n:num`; `1`] MOD_MULT) THEN
ASM_SIMP_TAC[ARITH_RULE `1 <= n ==> ~(n = 0)`;
MULT_CLAUSES;
EL];
ALL_TAC
] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN
MATCH_MP_TAC (GSYM
MOD_LT) THEN
MP_TAC (SPEC_ALL
INDEX_LT_LENGTH) THEN
ASM_REWRITE_TAC[] THEN
POP_ASSUM MP_TAC THEN ARITH_TAC);;
let NEXT_EL_POWER = prove(`!list (x:A) i.
ALL_DISTINCT list /\
MEM x list ==>
((\t.
NEXT_EL t list)
POWER i) x =
EL ((
INDEX x list + i) MOD (
LENGTH list)) list`,
GEN_TAC THEN GEN_TAC THEN
ABBREV_TAC `n =
LENGTH (list:(A)list)` THEN
ABBREV_TAC `k =
INDEX (x:A) list` THEN
INDUCT_TAC THENL
[
REWRITE_TAC[
ADD_0; Hypermap.POWER_0;
I_THM] THEN
STRIP_TAC THEN
SUBGOAL_THEN `k MOD n = k` (fun
th -> REWRITE_TAC[
th]) THENL
[
MATCH_MP_TAC
MOD_LT THEN
EXPAND_TAC "k" THEN EXPAND_TAC "n" THEN
ASM_REWRITE_TAC[GSYM
INDEX_LT_LENGTH];
ALL_TAC
] THEN
EXPAND_TAC "k" THEN
MATCH_MP_TAC (GSYM
EL_INDEX) THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
STRIP_TAC THEN
SUBGOAL_THEN `~(n = 0)` ASSUME_TAC THENL
[
POP_ASSUM MP_TAC THEN ASM_REWRITE_TAC[
MEM_EXISTS_EL] THEN
STRIP_TAC THEN UNDISCH_TAC `i' < n:num` THEN
ARITH_TAC;
ALL_TAC
] THEN
FIRST_X_ASSUM (MP_TAC o check(is_imp o concl)) THEN
ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
ASM_REWRITE_TAC[Hypermap.COM_POWER;
o_THM] THEN
ABBREV_TAC `y:A =
EL ((k + i) MOD n) list` THEN
MP_TAC (SPECL [`list:(A)list`; `y:A`]
NEXT_EL_MOD) THEN
ANTS_TAC THENL
[
REWRITE_TAC[
MEM_EXISTS_EL] THEN
EXISTS_TAC `(k + i) MOD n` THEN
ASM_REWRITE_TAC[] THEN
ASM_SIMP_TAC[
DIVISION];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> ASM_REWRITE_TAC[
th]) THEN
SUBGOAL_THEN `
INDEX (y:A) list = (k + i) MOD n` (fun
th -> REWRITE_TAC[
th]) THENL
[
EXPAND_TAC "y" THEN
MATCH_MP_TAC
INDEX_EL THEN
ASM_SIMP_TAC[
DIVISION];
ALL_TAC
] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN
ASM_CASES_TAC `n = 1` THENL
[
ASM_REWRITE_TAC[MOD_1];
ALL_TAC
] THEN
SUBGOAL_THEN `1 = 1 MOD n` (fun
th -> ONCE_REWRITE_TAC[
th]) THENL
[
MATCH_MP_TAC (GSYM
MOD_LT) THEN
ASM_REWRITE_TAC[ARITH_RULE `1 < n <=> ~(n = 0) /\ ~(n = 1)`];
ALL_TAC
] THEN
ASM_SIMP_TAC[
MOD_ADD_MOD] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN
ARITH_TAC);;
let NEXT_EL_ORBIT = prove(`!(list:(A)list) x.
ALL_DISTINCT list /\
MEM x list ==>
orbit_map (\t.
NEXT_EL t list) x =
set_of_list list`,
REPEAT STRIP_TAC THEN
ABBREV_TAC `n =
LENGTH (list:(A)list)` THEN
SUBGOAL_THEN `~(n = 0)` ASSUME_TAC THENL
[
UNDISCH_TAC `
MEM (x:A) list` THEN
ASM_REWRITE_TAC[
MEM_EXISTS_EL] THEN
STRIP_TAC THEN UNDISCH_TAC `i < n:num` THEN ARITH_TAC;
ALL_TAC
] THEN
REWRITE_TAC[Hypermap.orbit_map;
EXTENSION;
IN_SET_OF_LIST;
IN_ELIM_THM] THEN
GEN_TAC THEN EQ_TAC THENL
[
STRIP_TAC THEN POP_ASSUM MP_TAC THEN
ASM_SIMP_TAC[
NEXT_EL_POWER] THEN DISCH_TAC THEN
MATCH_MP_TAC
MEM_EL THEN
ASM_SIMP_TAC[
DIVISION];
ALL_TAC
] THEN
ASM_REWRITE_TAC[
MEM_EXISTS_EL] THEN
STRIP_TAC THEN
ASM_SIMP_TAC[
NEXT_EL_POWER] THEN
ABBREV_TAC `k =
INDEX (x:A) list` THEN
EXISTS_TAC `n - k + i:num` THEN
SUBGOAL_THEN `k < n:num` ASSUME_TAC THENL
[
EXPAND_TAC "k" THEN EXPAND_TAC "n" THEN
ASM_REWRITE_TAC[GSYM
INDEX_LT_LENGTH];
ALL_TAC
] THEN
REWRITE_TAC[
GE;
LE_0] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN
ASM_SIMP_TAC[ARITH_RULE `k < n ==> k + n - k + i = n + i:num`] THEN
MP_TAC (SPECL [`1`; `n:num`; `i:num`]
MOD_MULT_ADD) THEN
REWRITE_TAC[
MULT_CLAUSES] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
MATCH_MP_TAC (GSYM
MOD_LT) THEN
ASM_REWRITE_TAC[]);;
let ORBIT_SUBSET_LEMMA = prove(`!f s (x:A). x
IN s /\ (!y. y
IN s ==> f y
IN s)
==>
orbit_map f x
SUBSET s`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[Hypermap.orbit_map;
SUBSET;
IN_ELIM_THM] THEN
GEN_TAC THEN DISCH_THEN CHOOSE_TAC THEN POP_ASSUM MP_TAC THEN
SPEC_TAC (`x':A`, `y:A`) THEN
SPEC_TAC (`n:num`, `n:num`) THEN
INDUCT_TAC THEN ASM_SIMP_TAC[
GE;
LE_0; Hypermap.POWER_0;
I_THM] THEN
GEN_TAC THEN REWRITE_TAC[Hypermap.COM_POWER;
o_THM] THEN
DISCH_TAC THEN
FIRST_X_ASSUM (MP_TAC o SPEC `(f
POWER n) (x:A)`) THEN
ASM_REWRITE_TAC[
GE;
LE_0]);;
let ORBIT_MAP_RES = prove(`!f (x:A) s. x
IN s /\ (res f s)
permutes s
==>
orbit_map (res f s) x =
orbit_map f x`,
REPEAT STRIP_TAC THEN
MATCH_MP_TAC
ORBIT_MAP_RES_LEMMA THEN
MATCH_MP_TAC
ORBIT_SUBSET_LEMMA THEN
ASM_REWRITE_TAC[] THEN
REPEAT STRIP_TAC THEN
SUBGOAL_THEN `(f:A->A) y = (res f s) y` (fun
th -> REWRITE_TAC[
th]) THENL
[
ASM_REWRITE_TAC[res];
ALL_TAC
] THEN
MP_TAC (ISPECL [`res (f:A->A) s`; `s:A->bool`] Hypermap_and_fan.PERMUTES_IMP_INSIDE) THEN
ASM_SIMP_TAC[]);;
let ALL_DISTINCT_SUBLIST_UNIQUE = prove(`!l1 l2 (x:A) ll.
ALL_DISTINCT (
FLATTEN ll) /\
MEM l1 ll /\
MEM l2 ll /\
MEM x
l1 /\
MEM x l2
==>
l1 = l2`,
GEN_TAC THEN GEN_TAC THEN GEN_TAC THEN
LIST_INDUCT_TAC THEN REWRITE_TAC[
MEM] THEN
REWRITE_TAC[
FLATTEN;
ITLIST] THEN
REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THENL
[
FIRST_X_ASSUM (MP_TAC o check (fun
th -> (rator o concl)
th = `ALL_DISTINCT:(A)list->bool`)) THEN
ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
DISCH_TAC THEN
MATCH_MP_TAC
MEM_IMP_NOT_ALL_DISTINCT_APPEND THEN
EXISTS_TAC `x:A` THEN
FIRST_X_ASSUM (fun
th -> ASM_REWRITE_TAC[SYM
th]) THEN
REWRITE_TAC[GSYM
FLATTEN] THEN
REWRITE_TAC[
MEM_FLATTEN] THEN
EXISTS_TAC `l2:(A)list` THEN
ASM_REWRITE_TAC[];
FIRST_X_ASSUM (MP_TAC o check (fun
th -> (rator o concl)
th = `ALL_DISTINCT:(A)list->bool`)) THEN
ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
DISCH_TAC THEN
MATCH_MP_TAC
MEM_IMP_NOT_ALL_DISTINCT_APPEND THEN
EXISTS_TAC `x:A` THEN
FIRST_X_ASSUM (fun
th -> ASM_REWRITE_TAC[SYM
th]) THEN
REWRITE_TAC[GSYM
FLATTEN] THEN
REWRITE_TAC[
MEM_FLATTEN] THEN
EXISTS_TAC `l1:(A)list` THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
FIRST_X_ASSUM MATCH_MP_TAC THEN
ASM_REWRITE_TAC[] THEN
FIRST_X_ASSUM (MP_TAC o (fun
th -> MATCH_MP
ALL_DISTINCT_APPEND th)) THEN
SIMP_TAC[GSYM
FLATTEN]);;
(* Define nodes of a good hypermap *)
let SET_OF_LIST_FILTER = prove(`!P list:(A)list.
set_of_list (
FILTER P list) = {x |
MEM x list /\ P x}`,
GEN_TAC THEN LIST_INDUCT_TAC THEN REWRITE_TAC[
FILTER;
MEM] THENL
[
REWRITE_TAC[
set_of_list] THEN SET_TAC[];
ALL_TAC
] THEN
COND_CASES_TAC THENL
[
ASM_REWRITE_TAC[
set_of_list] THEN
POP_ASSUM MP_TAC THEN SET_TAC[];
ALL_TAC
] THEN
ASM_REWRITE_TAC[] THEN
POP_ASSUM MP_TAC THEN SET_TAC[]);;
let PREV_EL_LIST_PAIRS_GENERAL = prove(`!x (y:A) list.
MEM (x,y) (
list_pairs list)
==> ?z.
PREV_EL (x,y) (
list_pairs list) = (z, x) /\
MEM (z,x) (
list_pairs list)`,
REPEAT STRIP_TAC THEN
ABBREV_TAC `z =
FST (
PREV_EL (x:A,y) (
list_pairs list))` THEN
EXISTS_TAC `z:A` THEN
SUBGOAL_THEN `
PREV_EL (x:A,y) (
list_pairs list) = z,x` ASSUME_TAC THENL
[
POP_ASSUM (fun
th -> REWRITE_TAC[SYM
th]) THEN
REWRITE_TAC[
PREV_EL] THEN
ABBREV_TAC `k =
INDEX (x:A,y) (
list_pairs list)` THEN
ABBREV_TAC `n =
LENGTH (list:(A)list)` THEN
SUBGOAL_THEN `k < n:num` ASSUME_TAC THENL
[
MP_TAC (SPEC `list:(A)list`
LENGTH_LIST_PAIRS) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
EXPAND_TAC "k" THEN
ASM_REWRITE_TAC[GSYM
INDEX_LT_LENGTH];
ALL_TAC
] THEN
COND_CASES_TAC THENL
[
MP_TAC (ISPEC `
list_pairs (list:(A)list)`
LAST_EL) THEN
ANTS_TAC THENL
[
DISCH_TAC THEN
UNDISCH_TAC `
MEM (x:A,y) (
list_pairs list)` THEN
ASM_REWRITE_TAC[
MEM];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
ASM_REWRITE_TAC[
LENGTH_LIST_PAIRS] THEN
MP_TAC (SPECL [`n - 1`; `list:(A)list`]
EL_LIST_PAIRS) THEN
ASM_REWRITE_TAC[] THEN
ANTS_TAC THENL
[
MATCH_MP_TAC (ARITH_RULE `k < n ==> n - 1 < n`) THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th;
PAIR_EQ]) THEN
MP_TAC (ISPECL [`(x:A,y:A)`; `
list_pairs (list:(A)list)`]
EL_INDEX) THEN
ASM_REWRITE_TAC[] THEN
MP_TAC (SPECL [`0`; `list:(A)list`]
EL_LIST_PAIRS) THEN
ANTS_TAC THENL
[
POP_ASSUM (fun
th -> ASM_REWRITE_TAC[SYM
th]);
ALL_TAC
] THEN
DISCH_THEN (fun
th -> SIMP_TAC[
th;
PAIR_EQ]);
ALL_TAC
] THEN
MP_TAC (SPECL [`k - 1`; `list:(A)list`]
EL_LIST_PAIRS) THEN
ASM_SIMP_TAC[ARITH_RULE `k < n ==> k - 1 < n`;
PAIR_EQ] THEN
DISCH_THEN (fun
th -> ALL_TAC) THEN
ASM_SIMP_TAC[ARITH_RULE `k < n /\ ~(k = 0) ==> ~(k - 1 = n - 1)`] THEN
ASM_SIMP_TAC[ARITH_RULE `~(k = 0) ==> k - 1 + 1 = k`] THEN
EXPAND_TAC "k" THEN
MP_TAC (ISPECL [`(x:A,y:A)`; `
list_pairs (list:(A)list)`]
EL_INDEX) THEN
ASM_REWRITE_TAC[] THEN
ASM_SIMP_TAC[
EL_LIST_PAIRS;
PAIR_EQ];
ALL_TAC
] THEN
ASM_REWRITE_TAC[] THEN
POP_ASSUM (fun
th -> REWRITE_TAC[SYM
th]) THEN
MATCH_MP_TAC
MEM_PREV_EL THEN
ASM_REWRITE_TAC[]);;
let MEM_LIST_OF_DARTS = prove(`!d L.
MEM d (
list_of_darts L) <=>
?l:(A)list.
MEM l L /\
MEM d (
list_pairs l)`,
REPEAT GEN_TAC THEN EQ_TAC THENL
[
SPEC_TAC (`L:((A)list)list`, `L:((A)list)list`) THEN
LIST_INDUCT_TAC THEN REWRITE_TAC[
list_of_darts;
ITLIST;
MEM] THEN
REWRITE_TAC[GSYM
list_of_darts;
MEM_APPEND] THEN
STRIP_TAC THENL
[
EXISTS_TAC `h:(A)list` THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
FIRST_X_ASSUM (MP_TAC o check (is_imp o concl)) THEN
ASM_REWRITE_TAC[] THEN STRIP_TAC THEN
EXISTS_TAC `l:(A)list` THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
STRIP_TAC THEN
MATCH_MP_TAC
DART_IN_DARTS THEN
EXISTS_TAC `l:(A)list` THEN ASM_REWRITE_TAC[]);;
(* Theorems for special lists *)