1 (* ========================================================================= *)
2 (* Permutations, both general and specifically on finite sets. *)
3 (* ========================================================================= *)
5 parse_as_infix("permutes",(12,"right"));;
7 let permutes = new_definition
8 `p permutes s <=> (!x. ~(x IN s) ==> p(x) = x) /\ (!y. ?!x. p x = y)`;;
10 (* ------------------------------------------------------------------------- *)
11 (* Inverse function (on whole universe). *)
12 (* ------------------------------------------------------------------------- *)
14 let inverse = new_definition
15 `inverse(f) = \y. @x. f x = y`;;
17 let SURJECTIVE_INVERSE = prove
18 (`!f. (!y. ?x. f x = y) <=> !y. f(inverse f y) = y`,
19 REWRITE_TAC[SURJECTIVE_RIGHT_INVERSE; inverse] THEN MESON_TAC[]);;
21 let SURJECTIVE_INVERSE_o = prove
22 (`!f. (!y. ?x. f x = y) <=> (f o inverse f = I)`,
23 REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM; SURJECTIVE_INVERSE]);;
25 let INJECTIVE_INVERSE = prove
26 (`!f. (!x x'. f x = f x' ==> x = x') <=> !x. inverse f (f x) = x`,
29 let INJECTIVE_INVERSE_o = prove
30 (`!f. (!x x'. f x = f x' ==> x = x') <=> (inverse f o f = I)`,
31 REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM; INJECTIVE_INVERSE]);;
33 let INVERSE_UNIQUE_o = prove
34 (`!f g. f o g = I /\ g o f = I ==> inverse f = g`,
35 REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM] THEN
36 MESON_TAC[INJECTIVE_INVERSE; SURJECTIVE_INVERSE]);;
40 MATCH_MP_TAC INVERSE_UNIQUE_o THEN REWRITE_TAC[I_O_ID]);;
42 (* ------------------------------------------------------------------------- *)
44 (* ------------------------------------------------------------------------- *)
46 let swap = new_definition
47 `swap(i,j) k = if k = i then j else if k = j then i else k`;;
51 REWRITE_TAC[FUN_EQ_THM; swap; I_THM] THEN MESON_TAC[]);;
54 (`!a b. swap(a,b) = swap(b,a)`,
55 REWRITE_TAC[FUN_EQ_THM; swap; I_THM] THEN MESON_TAC[]);;
57 let SWAP_IDEMPOTENT = prove
58 (`!a b. swap(a,b) o swap(a,b) = I`,
59 REWRITE_TAC[FUN_EQ_THM; swap; o_THM; I_THM] THEN MESON_TAC[]);;
61 let INVERSE_SWAP = prove
62 (`!a b. inverse(swap(a,b)) = swap(a,b)`,
63 REPEAT GEN_TAC THEN MATCH_MP_TAC INVERSE_UNIQUE_o THEN
64 REWRITE_TAC[SWAP_SYM; SWAP_IDEMPOTENT]);;
66 let SWAP_GALOIS = prove
67 (`!a b x y. x = swap(a,b) y <=> y = swap(a,b) x`,
68 REWRITE_TAC[swap] THEN MESON_TAC[]);;
70 (* ------------------------------------------------------------------------- *)
71 (* Basic consequences of the definition. *)
72 (* ------------------------------------------------------------------------- *)
74 let PERMUTES_IN_IMAGE = prove
75 (`!p s x. p permutes s ==> (p(x) IN s <=> x IN s)`,
76 REWRITE_TAC[permutes] THEN MESON_TAC[]);;
78 let PERMUTES_IMAGE = prove
79 (`!p s. p permutes s ==> IMAGE p s = s`,
80 REWRITE_TAC[permutes; EXTENSION; IN_IMAGE] THEN MESON_TAC[]);;
82 let PERMUTES_INJECTIVE = prove
83 (`!p s. p permutes s ==> !x y. p(x) = p(y) <=> x = y`,
84 REWRITE_TAC[permutes] THEN MESON_TAC[]);;
86 let PERMUTES_SURJECTIVE = prove
87 (`!p s. p permutes s ==> !y. ?x. p(x) = y`,
88 REWRITE_TAC[permutes] THEN MESON_TAC[]);;
90 let PERMUTES_INVERSES_o = prove
91 (`!p s. p permutes s ==> p o inverse(p) = I /\ inverse(p) o p = I`,
92 REWRITE_TAC[GSYM INJECTIVE_INVERSE_o; GSYM SURJECTIVE_INVERSE_o] THEN
93 REWRITE_TAC[permutes] THEN MESON_TAC[]);;
95 let PERMUTES_INVERSES = prove
97 ==> (!x. p(inverse p x) = x) /\ (!x. inverse p (p x) = x)`,
98 REPEAT GEN_TAC THEN DISCH_THEN(MP_TAC o MATCH_MP PERMUTES_INVERSES_o) THEN
99 REWRITE_TAC[FUN_EQ_THM; o_THM; I_THM]);;
101 let PERMUTES_SUBSET = prove
102 (`!p s t. p permutes s /\ s SUBSET t ==> p permutes t`,
103 REWRITE_TAC[permutes; SUBSET] THEN MESON_TAC[]);;
105 let PERMUTES_EMPTY = prove
106 (`!p. p permutes {} <=> p = I`,
107 REWRITE_TAC[FUN_EQ_THM; I_THM; permutes; NOT_IN_EMPTY] THEN MESON_TAC[]);;
109 let PERMUTES_SING = prove
110 (`!p a. p permutes {a} <=> p = I`,
111 REWRITE_TAC[FUN_EQ_THM; I_THM; permutes; IN_SING] THEN MESON_TAC[]);;
113 let PERMUTES_UNIV = prove
114 (`!p. p permutes UNIV <=> !y:A. ?!x. p x = y`,
115 REWRITE_TAC[permutes; IN_UNIV] THEN MESON_TAC[]);;
117 let PERMUTES_INVERSE_EQ = prove
118 (`!p s. p permutes s ==> !x y. inverse p y = x <=> p x = y`,
119 REWRITE_TAC[permutes; inverse] THEN MESON_TAC[]);;
121 let PERMUTES_SWAP = prove
122 (`!a b s. a IN s /\ b IN s ==> swap(a,b) permutes s`,
123 REWRITE_TAC[permutes; swap] THEN MESON_TAC[]);;
125 let PERMUTES_SUPERSET = prove
126 (`!p s t. p permutes s /\ (!x. x IN (s DIFF t) ==> p(x) = x)
128 REWRITE_TAC[permutes; IN_DIFF] THEN MESON_TAC[]);;
130 let PERMUTES_BIJECTIONS = prove
131 (`!p q. (!x. x IN s ==> p x IN s) /\ (!x. ~(x IN s) ==> p x = x) /\
132 (!x. x IN s ==> q x IN s) /\ (!x. ~(x IN s) ==> q x = x) /\
133 (!x. p(q x) = x) /\ (!x. q(p x) = x)
135 REWRITE_TAC[permutes] THEN MESON_TAC[]);;
137 (* ------------------------------------------------------------------------- *)
138 (* Group properties. *)
139 (* ------------------------------------------------------------------------- *)
141 let PERMUTES_I = prove
143 REWRITE_TAC[permutes; I_THM] THEN MESON_TAC[]);;
145 let PERMUTES_COMPOSE = prove
146 (`!p q s. p permutes s /\ q permutes s ==> (q o p) permutes s`,
147 REWRITE_TAC[permutes; o_THM] THEN MESON_TAC[]);;
149 let PERMUTES_INVERSE = prove
150 (`!p s. p permutes s ==> inverse(p) permutes s`,
151 REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o MATCH_MP PERMUTES_INVERSE_EQ) THEN
152 POP_ASSUM MP_TAC THEN REWRITE_TAC[permutes] THEN MESON_TAC[]);;
154 let PERMUTES_INVERSE_INVERSE = prove
155 (`!p. p permutes s ==> inverse(inverse p) = p`,
156 SIMP_TAC[FUN_EQ_THM] THEN MESON_TAC[PERMUTES_INVERSE_EQ; PERMUTES_INVERSE]);;
158 (* ------------------------------------------------------------------------- *)
159 (* The number of permutations on a finite set. *)
160 (* ------------------------------------------------------------------------- *)
162 let PERMUTES_INSERT_LEMMA = prove
163 (`!p a:A s. p permutes (a INSERT s) ==> (swap(a,p(a)) o p) permutes s`,
164 REPEAT STRIP_TAC THEN MATCH_MP_TAC PERMUTES_SUPERSET THEN
165 EXISTS_TAC `(a:A) INSERT s` THEN CONJ_TAC THENL
166 [ASM_MESON_TAC[PERMUTES_SWAP; PERMUTES_IN_IMAGE;
167 IN_INSERT; PERMUTES_COMPOSE];
168 REWRITE_TAC[o_THM; swap; IN_INSERT; IN_DIFF] THEN ASM_MESON_TAC[]]);;
170 let PERMUTES_INSERT = prove
171 (`{p:A->A | p permutes (a INSERT s)} =
172 IMAGE (\(b,p). swap(a,b) o p)
173 {(b,p) | b IN a INSERT s /\ p IN {p | p permutes s}}`,
174 REWRITE_TAC[EXTENSION; IN_ELIM_PAIR_THM; IN_IMAGE; EXISTS_PAIR_THM] THEN
175 X_GEN_TAC `p:A->A` THEN REWRITE_TAC[IN_ELIM_THM] THEN
176 CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN EQ_TAC THENL
177 [DISCH_TAC THEN MAP_EVERY EXISTS_TAC
178 [`(p:A->A) a`; `swap(a,p a) o (p:A->A)`] THEN
179 ASM_SIMP_TAC[SWAP_IDEMPOTENT; o_ASSOC; I_O_ID; PERMUTES_INSERT_LEMMA] THEN
180 ASM_MESON_TAC[PERMUTES_IN_IMAGE; IN_INSERT];
181 REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN
182 MAP_EVERY X_GEN_TAC [`b:A`; `q:A->A`] THEN
183 STRIP_TAC THEN ASM_REWRITE_TAC[] THEN MATCH_MP_TAC PERMUTES_COMPOSE THEN
185 [ASM_MESON_TAC[PERMUTES_SUBSET; SUBSET; IN_INSERT];
186 MATCH_MP_TAC PERMUTES_SWAP THEN
187 ASM_MESON_TAC[PERMUTES_IN_IMAGE; IN_INSERT]]]);;
189 let HAS_SIZE_PERMUTATIONS = prove
190 (`!s:A->bool n. s HAS_SIZE n ==> {p | p permutes s} HAS_SIZE (FACT n)`,
191 REWRITE_TAC[HAS_SIZE; IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN
192 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
193 SIMP_TAC[PERMUTES_EMPTY; CARD_CLAUSES; SET_RULE `{x | x = a} = {a}`] THEN
194 SIMP_TAC[CARD_CLAUSES; FINITE_INSERT; FINITE_EMPTY] THEN
195 REWRITE_TAC[NOT_IN_EMPTY] THEN CONJ_TAC THENL
196 [GEN_TAC THEN DISCH_THEN(SUBST1_TAC o SYM) THEN CONV_TAC NUM_REDUCE_CONV;
198 MAP_EVERY X_GEN_TAC [`a:A`; `s:A->bool`] THEN REWRITE_TAC[GSYM HAS_SIZE] THEN
199 STRIP_TAC THEN X_GEN_TAC `k:num` THEN DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
200 REWRITE_TAC[FACT; PERMUTES_INSERT] THEN MATCH_MP_TAC HAS_SIZE_IMAGE_INJ THEN
201 ASM_SIMP_TAC[HAS_SIZE_PRODUCT; HAS_SIZE; FINITE_INSERT; CARD_CLAUSES] THEN
202 REWRITE_TAC[FORALL_PAIR_THM; IN_ELIM_PAIR_THM; IN_ELIM_THM; PAIR_EQ] THEN
203 CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
204 MAP_EVERY X_GEN_TAC [`b:A`; `q:A->A`; `c:A`; `r:A->A`] THEN
205 STRIP_TAC THEN SUBGOAL_THEN `c:A = b` SUBST_ALL_TAC THENL
206 [FIRST_X_ASSUM(MP_TAC o C AP_THM `a:A`) THEN REWRITE_TAC[o_THM; swap] THEN
207 SUBGOAL_THEN `(q:A->A) a = a /\ (r:A->A) a = a` (fun t -> SIMP_TAC[t]) THEN
208 ASM_MESON_TAC[permutes];
209 FIRST_X_ASSUM(MP_TAC o AP_TERM `(\q:A->A. swap(a:A,b) o q)`) THEN
210 ASM_SIMP_TAC[SWAP_IDEMPOTENT; o_ASSOC; I_O_ID]]);;
212 let FINITE_PERMUTATIONS = prove
213 (`!s. FINITE s ==> FINITE {p | p permutes s}`,
214 MESON_TAC[HAS_SIZE_PERMUTATIONS; HAS_SIZE]);;
216 let CARD_PERMUTATIONS = prove
217 (`!s. FINITE s ==> CARD {p | p permutes s} = FACT(CARD s)`,
218 MESON_TAC[HAS_SIZE; HAS_SIZE_PERMUTATIONS]);;
220 (* ------------------------------------------------------------------------- *)
221 (* Alternative characterizations of permutation of finite set. *)
222 (* ------------------------------------------------------------------------- *)
224 let PERMUTES_FINITE_INJECTIVE = prove
227 ==> (p permutes s <=>
228 (!x. ~(x IN s) ==> p x = x) /\
229 (!x. x IN s ==> p x IN s) /\
230 (!x y. x IN s /\ y IN s /\ p x = p y ==> x = y))`,
231 REWRITE_TAC[permutes] THEN REPEAT STRIP_TAC THEN
232 MATCH_MP_TAC(TAUT `(p ==> (q <=> r)) ==> (p /\ q <=> p /\ r)`) THEN
233 DISCH_TAC THEN EQ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN STRIP_TAC THEN
234 FIRST_ASSUM(MP_TAC o SPEC `p:A->A` o MATCH_MP
235 (REWRITE_RULE[IMP_CONJ] SURJECTIVE_IFF_INJECTIVE)) THEN
236 ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IMP_IMP; GSYM CONJ_ASSOC] THEN
237 STRIP_TAC THEN X_GEN_TAC `y:A` THEN
238 ASM_CASES_TAC `(y:A) IN s` THEN ASM_MESON_TAC[]);;
240 let PERMUTES_FINITE_SURJECTIVE = prove
243 ==> (p permutes s <=>
244 (!x. ~(x IN s) ==> p x = x) /\ (!x. x IN s ==> p x IN s) /\
245 (!y. y IN s ==> ?x. x IN s /\ p x = y))`,
246 REWRITE_TAC[permutes] THEN REPEAT STRIP_TAC THEN
247 MATCH_MP_TAC(TAUT `(p ==> (q <=> r)) ==> (p /\ q <=> p /\ r)`) THEN
248 DISCH_TAC THEN EQ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN STRIP_TAC THEN
249 FIRST_ASSUM(MP_TAC o SPEC `p:A->A` o MATCH_MP
250 (REWRITE_RULE[IMP_CONJ] SURJECTIVE_IFF_INJECTIVE)) THEN
251 ASM_REWRITE_TAC[SUBSET; FORALL_IN_IMAGE; IMP_IMP; GSYM CONJ_ASSOC] THEN
252 STRIP_TAC THEN X_GEN_TAC `y:A` THEN
253 ASM_CASES_TAC `(y:A) IN s` THEN ASM_MESON_TAC[]);;
255 (* ------------------------------------------------------------------------- *)
256 (* Permutations of index set for iterated operations. *)
257 (* ------------------------------------------------------------------------- *)
259 let ITERATE_PERMUTE = prove
261 ==> !f p s. p permutes s ==> iterate op s f = iterate op s (f o p)`,
262 REPEAT STRIP_TAC THEN
263 FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP ITERATE_BIJECTION) THEN
264 ASM_MESON_TAC[permutes]);;
266 let NSUM_PERMUTE = prove
267 (`!f p s. p permutes s ==> nsum s f = nsum s (f o p)`,
268 REWRITE_TAC[nsum] THEN MATCH_MP_TAC ITERATE_PERMUTE THEN
269 REWRITE_TAC[MONOIDAL_ADD]);;
271 let NSUM_PERMUTE_NUMSEG = prove
272 (`!f p m n. p permutes m..n ==> nsum(m..n) f = nsum(m..n) (f o p)`,
273 MESON_TAC[NSUM_PERMUTE; FINITE_NUMSEG]);;
275 let SUM_PERMUTE = prove
276 (`!f p s. p permutes s ==> sum s f = sum s (f o p)`,
277 REWRITE_TAC[sum] THEN MATCH_MP_TAC ITERATE_PERMUTE THEN
278 REWRITE_TAC[MONOIDAL_REAL_ADD]);;
280 let SUM_PERMUTE_NUMSEG = prove
281 (`!f p m n. p permutes m..n ==> sum(m..n) f = sum(m..n) (f o p)`,
282 MESON_TAC[SUM_PERMUTE; FINITE_NUMSEG]);;
284 (* ------------------------------------------------------------------------- *)
285 (* Various combinations of transpositions with 2, 1 and 0 common elements. *)
286 (* ------------------------------------------------------------------------- *)
288 let SWAP_COMMON = prove
289 (`!a b c:A. ~(a = c) /\ ~(b = c)
290 ==> swap(a,b) o swap(a,c) = swap(b,c) o swap(a,b)`,
291 REPEAT GEN_TAC THEN REWRITE_TAC[FUN_EQ_THM; swap; o_THM; I_THM] THEN
292 DISCH_TAC THEN X_GEN_TAC `x:A` THEN
293 MAP_EVERY ASM_CASES_TAC [`x:A = a`; `x:A = b`; `x:A = c`] THEN
294 REPEAT(FIRST_X_ASSUM SUBST_ALL_TAC) THEN ASM_REWRITE_TAC[] THEN
297 let SWAP_COMMON' = prove
298 (`!a b c:A. ~(a = b) /\ ~(a = c)
299 ==> swap(a,c) o swap(b,c) = swap(b,c) o swap(a,b)`,
300 REPEAT STRIP_TAC THEN
301 GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [SWAP_SYM] THEN
302 ASM_SIMP_TAC[GSYM SWAP_COMMON] THEN REWRITE_TAC[SWAP_SYM]);;
304 let SWAP_INDEPENDENT = prove
305 (`!a b c d:A. ~(a = c) /\ ~(a = d) /\ ~(b = c) /\ ~(b = d)
306 ==> swap(a,b) o swap(c,d) = swap(c,d) o swap(a,b)`,
307 REPEAT GEN_TAC THEN REWRITE_TAC[FUN_EQ_THM; swap; o_THM; I_THM] THEN
308 DISCH_TAC THEN X_GEN_TAC `x:A` THEN
309 MAP_EVERY ASM_CASES_TAC [`x:A = a`; `x:A = b`; `x:A = c`] THEN
310 REPEAT(FIRST_X_ASSUM SUBST_ALL_TAC) THEN ASM_REWRITE_TAC[] THEN
313 (* ------------------------------------------------------------------------- *)
314 (* Permutations as transposition sequences. *)
315 (* ------------------------------------------------------------------------- *)
317 let swapseq_RULES,swapseq_INDUCT,swapseq_CASES = new_inductive_definition
319 (!a b p n. swapseq n p /\ ~(a = b) ==> swapseq (SUC n) (swap(a,b) o p))`;;
321 let permutation = new_definition
322 `permutation p <=> ?n. swapseq n p`;;
324 (* ------------------------------------------------------------------------- *)
325 (* Some closure properties of the set of permutations, with lengths. *)
326 (* ------------------------------------------------------------------------- *)
328 let SWAPSEQ_I = CONJUNCT1 swapseq_RULES;;
330 let PERMUTATION_I = prove
332 REWRITE_TAC[permutation] THEN MESON_TAC[SWAPSEQ_I]);;
334 let SWAPSEQ_SWAP = prove
335 (`!a b. swapseq (if a = b then 0 else 1) (swap(a,b))`,
336 REPEAT GEN_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[num_CONV `1`] THEN
337 ASM_MESON_TAC[swapseq_RULES; I_O_ID; SWAPSEQ_I; SWAP_REFL]);;
339 let PERMUTATION_SWAP = prove
340 (`!a b. permutation(swap(a,b))`,
341 REWRITE_TAC[permutation] THEN MESON_TAC[SWAPSEQ_SWAP]);;
343 let SWAPSEQ_COMPOSE = prove
344 (`!n p m q. swapseq n p /\ swapseq m q ==> swapseq (n + m) (p o q)`,
345 REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
346 MATCH_MP_TAC swapseq_INDUCT THEN
347 REWRITE_TAC[ADD_CLAUSES; I_O_ID; GSYM o_ASSOC] THEN
348 MESON_TAC[swapseq_RULES]);;
350 let PERMUTATION_COMPOSE = prove
351 (`!p q. permutation p /\ permutation q ==> permutation(p o q)`,
352 REWRITE_TAC[permutation] THEN MESON_TAC[SWAPSEQ_COMPOSE]);;
354 let SWAPSEQ_ENDSWAP = prove
355 (`!n p a b:A. swapseq n p /\ ~(a = b) ==> swapseq (SUC n) (p o swap(a,b))`,
356 REWRITE_TAC[RIGHT_FORALL_IMP_THM; IMP_CONJ] THEN
357 MATCH_MP_TAC swapseq_INDUCT THEN REWRITE_TAC[I_O_ID; GSYM o_ASSOC] THEN
358 MESON_TAC[o_ASSOC; swapseq_RULES; I_O_ID]);;
360 let SWAPSEQ_INVERSE_EXISTS = prove
361 (`!n p:A->A. swapseq n p ==> ?q. swapseq n q /\ p o q = I /\ q o p = I`,
362 MATCH_MP_TAC swapseq_INDUCT THEN CONJ_TAC THENL
363 [MESON_TAC[I_O_ID; swapseq_RULES]; ALL_TAC] THEN
364 REPEAT STRIP_TAC THEN
365 MP_TAC(SPECL [`n:num`; `q:A->A`; `a:A`; `b:A`] SWAPSEQ_ENDSWAP) THEN
366 ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
367 EXISTS_TAC `(q:A->A) o swap (a,b)` THEN
368 ASM_REWRITE_TAC[GSYM o_ASSOC] THEN
369 GEN_REWRITE_TAC (BINOP_CONV o LAND_CONV o RAND_CONV) [o_ASSOC] THEN
370 ASM_REWRITE_TAC[SWAP_IDEMPOTENT; I_O_ID]);;
372 let SWAPSEQ_INVERSE = prove
373 (`!n p. swapseq n p ==> swapseq n (inverse p)`,
374 MESON_TAC[SWAPSEQ_INVERSE_EXISTS; INVERSE_UNIQUE_o]);;
376 let PERMUTATION_INVERSE = prove
377 (`!p. permutation p ==> permutation(inverse p)`,
378 REWRITE_TAC[permutation] THEN MESON_TAC[SWAPSEQ_INVERSE]);;
380 (* ------------------------------------------------------------------------- *)
381 (* The identity map only has even transposition sequences. *)
382 (* ------------------------------------------------------------------------- *)
384 let SYMMETRY_LEMMA = prove
385 (`(!a b c d. P a b c d ==> P a b d c) /\
386 (!a b c d. ~(a = b) /\ ~(c = d) /\
387 (a = c /\ b = d \/ a = c /\ ~(b = d) \/ ~(a = c) /\ b = d \/
388 ~(a = c) /\ ~(a = d) /\ ~(b = c) /\ ~(b = d))
390 ==> (!a b c d:A. ~(a = b) /\ ~(c = d) ==> P a b c d)`,
391 REPEAT STRIP_TAC THEN MAP_EVERY ASM_CASES_TAC
392 [`a:A = c`; `a:A = d`; `b:A = c`; `b:A = d`] THEN
395 let SWAP_GENERAL = prove
398 ==> swap(a,b) o swap(c,d) = I \/
399 ?x y z. ~(x = a) /\ ~(y = a) /\ ~(z = a) /\ ~(x = y) /\
400 swap(a,b) o swap(c,d) = swap(x,y) o swap(a,z)`,
401 MATCH_MP_TAC SYMMETRY_LEMMA THEN CONJ_TAC THENL
402 [REWRITE_TAC[SWAP_SYM] THEN SIMP_TAC[]; ALL_TAC] THEN
403 REPEAT STRIP_TAC THEN REPEAT(FIRST_X_ASSUM SUBST_ALL_TAC) THENL
404 [MESON_TAC[SWAP_IDEMPOTENT];
405 DISJ2_TAC THEN MAP_EVERY EXISTS_TAC [`b:A`; `d:A`; `b:A`] THEN
406 ASM_MESON_TAC[SWAP_COMMON];
407 DISJ2_TAC THEN MAP_EVERY EXISTS_TAC [`c:A`; `d:A`; `c:A`] THEN
408 ASM_MESON_TAC[SWAP_COMMON'];
409 DISJ2_TAC THEN MAP_EVERY EXISTS_TAC [`c:A`; `d:A`; `b:A`] THEN
410 ASM_MESON_TAC[SWAP_INDEPENDENT]]);;
412 let FIXING_SWAPSEQ_DECREASE = prove
414 swapseq n p /\ ~(a = b) /\ (swap(a,b) o p) a = a
415 ==> ~(n = 0) /\ swapseq (n - 1) (swap(a,b) o p)`,
416 INDUCT_TAC THEN REPEAT GEN_TAC THEN
417 GEN_REWRITE_TAC (LAND_CONV o LAND_CONV) [swapseq_CASES] THEN
418 REWRITE_TAC[NOT_SUC] THENL
419 [DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
420 ASM_REWRITE_TAC[I_THM; o_THM; swap] THEN MESON_TAC[];
422 REWRITE_TAC[LEFT_IMP_EXISTS_THM; LEFT_AND_EXISTS_THM] THEN
423 MAP_EVERY X_GEN_TAC [`c:A`; `d:A`; `q:A->A`; `m:num`] THEN
424 REWRITE_TAC[SUC_INJ; GSYM CONJ_ASSOC] THEN
425 DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
426 FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
427 DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
428 FIRST_X_ASSUM SUBST_ALL_TAC THEN REWRITE_TAC[o_ASSOC] THEN STRIP_TAC THEN
429 MP_TAC(SPECL [`a:A`; `b:A`; `c:A`; `d:A`] SWAP_GENERAL) THEN
430 ASM_REWRITE_TAC[] THEN
431 DISCH_THEN(DISJ_CASES_THEN2 SUBST_ALL_TAC MP_TAC) THEN
432 ASM_REWRITE_TAC[I_O_ID; SUC_SUB1; LEFT_IMP_EXISTS_THM] THEN
433 MAP_EVERY X_GEN_TAC [`x:A`; `y:A`; `z:A`] THEN
434 REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
435 DISCH_THEN SUBST_ALL_TAC THEN FIRST_X_ASSUM(MP_TAC o SPECL
436 [`q:A->A`; `a:A`; `z:A`]) THEN
438 [ASM_REWRITE_TAC[] THEN
439 FIRST_X_ASSUM(MP_TAC o check(is_eq o concl)) THEN
440 REWRITE_TAC[GSYM o_ASSOC] THEN
441 ABBREV_TAC `r:A->A = swap(a:A,z) o q` THEN
442 ASM_REWRITE_TAC[FUN_EQ_THM; o_THM; swap] THEN ASM_MESON_TAC[];
443 SPEC_TAC(`n:num`,`n:num`) THEN INDUCT_TAC THEN
444 REWRITE_TAC[NOT_SUC; SUC_SUB1; GSYM o_ASSOC] THEN
445 ASM_MESON_TAC[swapseq_RULES]]);;
447 let SWAPSEQ_IDENTITY_EVEN = prove
448 (`!n. swapseq n (I:A->A) ==> EVEN n`,
449 MATCH_MP_TAC num_WF THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
450 GEN_REWRITE_TAC LAND_CONV [swapseq_CASES] THEN
451 DISCH_THEN(DISJ_CASES_THEN2 (SUBST_ALL_TAC o CONJUNCT1) MP_TAC) THEN
452 REWRITE_TAC[EVEN; LEFT_IMP_EXISTS_THM] THEN
453 MAP_EVERY X_GEN_TAC [`a:A`; `b:A`; `p:A->A`; `m:num`] THEN
454 DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
455 MP_TAC(SPECL [`m:num`; `p:A->A`; `a:A`; `b:A`] FIXING_SWAPSEQ_DECREASE) THEN
456 ASM_REWRITE_TAC[I_THM] THEN STRIP_TAC THEN
457 FIRST_X_ASSUM(MP_TAC o SPEC `m - 1`) THEN
458 UNDISCH_THEN `SUC m = n` (SUBST_ALL_TAC o SYM) THEN
459 ASM_REWRITE_TAC[ARITH_RULE `m - 1 < SUC m`] THEN UNDISCH_TAC `~(m = 0)` THEN
460 SPEC_TAC(`m:num`,`m:num`) THEN INDUCT_TAC THEN
461 REWRITE_TAC[SUC_SUB1; EVEN]);;
463 (* ------------------------------------------------------------------------- *)
464 (* Therefore we have a welldefined notion of parity. *)
465 (* ------------------------------------------------------------------------- *)
467 let evenperm = new_definition `evenperm(p) = EVEN(@n. swapseq n p)`;;
469 let SWAPSEQ_EVEN_EVEN = prove
470 (`!m n p:A->A. swapseq m p /\ swapseq n p ==> (EVEN m <=> EVEN n)`,
471 REPEAT STRIP_TAC THEN
472 FIRST_X_ASSUM(MP_TAC o MATCH_MP SWAPSEQ_INVERSE_EXISTS) THEN
474 FIRST_X_ASSUM(MP_TAC o AP_TERM `swapseq (n + m) :(A->A)->bool`) THEN
475 ASM_SIMP_TAC[SWAPSEQ_COMPOSE] THEN
476 DISCH_THEN(MP_TAC o MATCH_MP SWAPSEQ_IDENTITY_EVEN) THEN
477 SIMP_TAC[EVEN_ADD]);;
479 let EVENPERM_UNIQUE = prove
480 (`!n p b. swapseq n p /\ EVEN n = b ==> evenperm p = b`,
481 REWRITE_TAC[evenperm] THEN MESON_TAC[SWAPSEQ_EVEN_EVEN]);;
483 (* ------------------------------------------------------------------------- *)
484 (* And it has the expected composition properties. *)
485 (* ------------------------------------------------------------------------- *)
487 let EVENPERM_I = prove
489 MATCH_MP_TAC EVENPERM_UNIQUE THEN MESON_TAC[swapseq_RULES; EVEN]);;
491 let EVENPERM_SWAP = prove
492 (`!a b:A. evenperm(swap(a,b)) = (a = b)`,
493 REPEAT GEN_TAC THEN MATCH_MP_TAC EVENPERM_UNIQUE THEN
494 MESON_TAC[SWAPSEQ_SWAP; NUM_RED_CONV `EVEN 0`; NUM_RED_CONV `EVEN 1`]);;
496 let EVENPERM_COMPOSE = prove
497 (`!p q. permutation p /\ permutation q
498 ==> evenperm (p o q) = (evenperm p = evenperm q)`,
499 REWRITE_TAC[permutation; LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] THEN
500 REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN REPEAT GEN_TAC THEN
501 DISCH_THEN(fun th -> ASSUME_TAC th THEN
502 ASSUME_TAC(MATCH_MP SWAPSEQ_COMPOSE th)) THEN
503 ASM_MESON_TAC[EVENPERM_UNIQUE; SWAPSEQ_COMPOSE; EVEN_ADD]);;
505 let EVENPERM_INVERSE = prove
506 (`!p. permutation p ==> evenperm(inverse p) = evenperm p`,
507 REWRITE_TAC[permutation] THEN REPEAT STRIP_TAC THEN
508 MATCH_MP_TAC EVENPERM_UNIQUE THEN
509 ASM_MESON_TAC[SWAPSEQ_INVERSE; EVENPERM_UNIQUE]);;
511 (* ------------------------------------------------------------------------- *)
512 (* A more abstract characterization of permutations. *)
513 (* ------------------------------------------------------------------------- *)
515 let PERMUTATION_BIJECTIVE = prove
516 (`!p. permutation p ==> !y. ?!x. p(x) = y`,
517 REWRITE_TAC[permutation] THEN REPEAT STRIP_TAC THEN
518 FIRST_X_ASSUM(MP_TAC o MATCH_MP SWAPSEQ_INVERSE_EXISTS) THEN
519 REWRITE_TAC[FUN_EQ_THM; I_THM; o_THM; LEFT_IMP_EXISTS_THM] THEN
522 let PERMUTATION_FINITE_SUPPORT = prove
523 (`!p. permutation p ==> FINITE {x:A | ~(p x = x)}`,
524 REWRITE_TAC[permutation; LEFT_IMP_EXISTS_THM] THEN
525 ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN MATCH_MP_TAC swapseq_INDUCT THEN
526 REWRITE_TAC[I_THM; FINITE_RULES; SET_RULE `{x | F} = {}`] THEN
527 MAP_EVERY X_GEN_TAC [`a:A`; `b:A`; `p:A->A`] THEN
528 STRIP_TAC THEN MATCH_MP_TAC FINITE_SUBSET THEN
529 EXISTS_TAC `(a:A) INSERT b INSERT {x | ~(p x = x)}` THEN
530 ASM_REWRITE_TAC[FINITE_INSERT; SUBSET; IN_INSERT; IN_ELIM_THM] THEN
531 REWRITE_TAC[o_THM; swap] THEN MESON_TAC[]);;
533 let PERMUTATION_LEMMA = prove
536 (!y. ?!x. p(x) = y) /\ (!x. ~(x IN s) ==> p x = x)
538 ONCE_REWRITE_TAC[IMP_CONJ] THEN REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN
539 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN CONJ_TAC THENL
540 [REWRITE_TAC[NOT_IN_EMPTY] THEN REPEAT STRIP_TAC THEN
541 SUBGOAL_THEN `p:A->A = I` (fun th -> REWRITE_TAC[th; PERMUTATION_I]) THEN
542 ASM_REWRITE_TAC[FUN_EQ_THM; I_THM];
544 MAP_EVERY X_GEN_TAC [`a:A`; `s:A->bool`] THEN STRIP_TAC THEN
545 REWRITE_TAC[IN_INSERT] THEN REPEAT STRIP_TAC THEN
546 SUBGOAL_THEN `permutation((swap(a,p(a)) o swap(a,p(a))) o (p:A->A))`
547 MP_TAC THENL [ALL_TAC; REWRITE_TAC[SWAP_IDEMPOTENT; I_O_ID]] THEN
548 REWRITE_TAC[GSYM o_ASSOC] THEN MATCH_MP_TAC PERMUTATION_COMPOSE THEN
549 REWRITE_TAC[PERMUTATION_SWAP] THEN FIRST_X_ASSUM MATCH_MP_TAC THEN
551 [UNDISCH_TAC `!y. ?!x. (p:A->A) x = y` THEN
552 REWRITE_TAC[EXISTS_UNIQUE_THM; swap; o_THM] THEN
553 ASM_CASES_TAC `(p:A->A) a = a` THEN ASM_REWRITE_TAC[] THENL
554 [ASM_MESON_TAC[]; ALL_TAC] THEN
556 `(if p then x else y) = a <=> if p then x = a else y = a`] THEN
557 REWRITE_TAC[TAUT `(if p then x else y) <=> p /\ x \/ ~p /\ y`] THEN
559 REWRITE_TAC[swap; o_THM] THEN
560 ASM_CASES_TAC `(p:A->A) a = a` THEN ASM_REWRITE_TAC[] THEN
563 let PERMUTATION = prove
564 (`!p. permutation p <=> (!y. ?!x. p(x) = y) /\ FINITE {x:A | ~(p(x) = x)}`,
565 GEN_TAC THEN EQ_TAC THEN
566 SIMP_TAC[PERMUTATION_BIJECTIVE; PERMUTATION_FINITE_SUPPORT] THEN
567 STRIP_TAC THEN MATCH_MP_TAC PERMUTATION_LEMMA THEN
568 EXISTS_TAC `{x:A | ~(p x = x)}` THEN
569 ASM_SIMP_TAC[IN_ELIM_THM]);;
571 let PERMUTATION_INVERSE_WORKS = prove
572 (`!p. permutation p ==> inverse p o p = I /\ p o inverse p = I`,
573 MESON_TAC[PERMUTATION_BIJECTIVE; SURJECTIVE_INVERSE_o;
574 INJECTIVE_INVERSE_o]);;
576 let PERMUTATION_INVERSE_COMPOSE = prove
577 (`!p q. permutation p /\ permutation q
578 ==> inverse(p o q) = inverse q o inverse p`,
579 REPEAT STRIP_TAC THEN MATCH_MP_TAC INVERSE_UNIQUE_o THEN
580 REPEAT(FIRST_X_ASSUM(MP_TAC o MATCH_MP PERMUTATION_INVERSE_WORKS)) THEN
581 REWRITE_TAC[GSYM o_ASSOC] THEN REPEAT STRIP_TAC THEN
582 GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [o_ASSOC] THEN
583 ASM_REWRITE_TAC[I_O_ID]);;
585 let PERMUTATION_COMPOSE_EQ = prove
586 (`(!p q:A->A. permutation(p) ==> (permutation(p o q) <=> permutation q)) /\
587 (!p q:A->A. permutation(q) ==> (permutation(p o q) <=> permutation p))`,
588 REPEAT STRIP_TAC THEN
589 FIRST_ASSUM(ASSUME_TAC o MATCH_MP PERMUTATION_INVERSE) THEN
590 EQ_TAC THEN ASM_SIMP_TAC[PERMUTATION_COMPOSE] THENL
591 [DISCH_THEN(MP_TAC o SPEC `inverse(p:A->A)` o MATCH_MP
592 (REWRITE_RULE[IMP_CONJ_ALT] PERMUTATION_COMPOSE));
593 DISCH_THEN(MP_TAC o SPEC `inverse(q:A->A)` o MATCH_MP
594 (REWRITE_RULE[IMP_CONJ] PERMUTATION_COMPOSE))] THEN
595 ASM_SIMP_TAC[GSYM o_ASSOC; PERMUTATION_INVERSE_WORKS] THEN
596 ASM_SIMP_TAC[o_ASSOC; PERMUTATION_INVERSE_WORKS] THEN
597 REWRITE_TAC[I_O_ID]);;
599 let PERMUTATION_COMPOSE_SWAP = prove
600 (`(!p a b:A. permutation(swap(a,b) o p) <=> permutation p) /\
601 (!p a b:A. permutation(p o swap(a,b)) <=> permutation p)`,
602 SIMP_TAC[PERMUTATION_COMPOSE_EQ; PERMUTATION_SWAP]);;
604 (* ------------------------------------------------------------------------- *)
605 (* Relation to "permutes". *)
606 (* ------------------------------------------------------------------------- *)
608 let PERMUTATION_PERMUTES = prove
609 (`!p:A->A. permutation p <=> ?s. FINITE s /\ p permutes s`,
610 GEN_TAC THEN REWRITE_TAC[PERMUTATION; permutes] THEN
611 EQ_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THENL
612 [EXISTS_TAC `{x:A | ~(p x = x)}` THEN ASM_SIMP_TAC[IN_ELIM_THM];
613 MATCH_MP_TAC FINITE_SUBSET THEN EXISTS_TAC `s:A->bool` THEN
614 ASM_SIMP_TAC[IN_ELIM_THM; SUBSET] THEN ASM_MESON_TAC[]]);;
616 (* ------------------------------------------------------------------------- *)
617 (* Hence a sort of induction principle composing by swaps. *)
618 (* ------------------------------------------------------------------------- *)
620 let PERMUTES_INDUCT = prove
623 (!a b:A p. a IN s /\ b IN s /\ P p /\ permutation p
624 ==> P (swap(a,b) o p))
625 ==> (!p. p permutes s ==> P p)`,
626 ONCE_REWRITE_TAC[TAUT `a /\ b /\ c ==> d <=> b ==> a ==> c ==> d`] THEN
627 REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN GEN_TAC THEN DISCH_TAC THEN
628 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
629 ASM_REWRITE_TAC[PERMUTES_EMPTY; IN_INSERT] THEN REPEAT STRIP_TAC THEN
630 ASM_REWRITE_TAC[] THEN
631 SUBGOAL_THEN `p = swap(x,p x) o swap(x,p x) o (p:A->A)` SUBST1_TAC THENL
632 [REWRITE_TAC[o_ASSOC; SWAP_IDEMPOTENT; I_O_ID]; ALL_TAC] THEN
633 FIRST_X_ASSUM(MP_TAC o check (is_imp o concl)) THEN
634 ANTS_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
635 DISCH_THEN(fun th -> FIRST_X_ASSUM MATCH_MP_TAC THEN ASSUME_TAC th) THEN
636 ASM_MESON_TAC[PERMUTES_IN_IMAGE; IN_INSERT; PERMUTES_INSERT_LEMMA;
637 PERMUTATION_PERMUTES; FINITE_INSERT; PERMUTATION_COMPOSE;
640 (* ------------------------------------------------------------------------- *)
641 (* Sign of a permutation as a real number. *)
642 (* ------------------------------------------------------------------------- *)
644 let sign = new_definition
645 `(sign p):real = if evenperm p then &1 else -- &1`;;
648 (`!p. ~(sign p = &0)`,
649 REWRITE_TAC[sign] THEN REAL_ARITH_TAC);;
653 REWRITE_TAC[sign; EVENPERM_I]);;
655 let SIGN_INVERSE = prove
656 (`!p. permutation p ==> sign(inverse p) = sign p`,
657 SIMP_TAC[sign; EVENPERM_INVERSE] THEN REAL_ARITH_TAC);;
659 let SIGN_COMPOSE = prove
660 (`!p q. permutation p /\ permutation q ==> sign(p o q) = sign(p) * sign(q)`,
661 SIMP_TAC[sign; EVENPERM_COMPOSE] THEN REAL_ARITH_TAC);;
663 let SIGN_SWAP = prove
664 (`!a b. sign(swap(a,b)) = if a = b then &1 else -- &1`,
665 REWRITE_TAC[sign; EVENPERM_SWAP]);;
667 let SIGN_IDEMPOTENT = prove
668 (`!p. sign(p) * sign(p) = &1`,
669 GEN_TAC THEN REWRITE_TAC[sign] THEN
670 COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN CONV_TAC REAL_RAT_REDUCE_CONV);;
672 let REAL_ABS_SIGN = prove
673 (`!p. abs(sign p) = &1`,
674 REWRITE_TAC[sign] THEN REAL_ARITH_TAC);;
676 (* ------------------------------------------------------------------------- *)
677 (* More lemmas about permutations. *)
678 (* ------------------------------------------------------------------------- *)
680 let PERMUTES_NUMSET_LE = prove
681 (`!p s:num->bool. p permutes s /\ (!i. i IN s ==> p(i) <= i) ==> p = I`,
682 REPEAT GEN_TAC THEN REWRITE_TAC[FUN_EQ_THM; I_THM] THEN STRIP_TAC THEN
683 MATCH_MP_TAC num_WF THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
684 ASM_CASES_TAC `(n:num) IN s` THENL [ALL_TAC; ASM_MESON_TAC[permutes]] THEN
685 ASM_SIMP_TAC[GSYM LE_ANTISYM] THEN REWRITE_TAC[GSYM NOT_LT] THEN
686 ASM_MESON_TAC[PERMUTES_INJECTIVE; LT_REFL]);;
688 let PERMUTES_NUMSET_GE = prove
689 (`!p s:num->bool. p permutes s /\ (!i. i IN s ==> i <= p(i)) ==> p = I`,
690 REPEAT STRIP_TAC THEN
691 MP_TAC(SPECL [`inverse(p:num->num)`; `s:num->bool`] PERMUTES_NUMSET_LE) THEN
693 [ASM_MESON_TAC[PERMUTES_INVERSE; PERMUTES_INVERSES; PERMUTES_IN_IMAGE];
694 ASM_MESON_TAC[PERMUTES_INVERSE_INVERSE; INVERSE_I]]);;
696 let IMAGE_INVERSE_PERMUTATIONS = prove
697 (`!s:A->bool. {inverse p | p permutes s} = {p | p permutes s}`,
698 REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
699 MESON_TAC[PERMUTES_INVERSE_INVERSE; PERMUTES_INVERSE]);;
701 let IMAGE_COMPOSE_PERMUTATIONS_L = prove
702 (`!s q:A->A. q permutes s ==> {q o p | p permutes s} = {p | p permutes s}`,
703 REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
704 X_GEN_TAC `p:A->A` THEN EQ_TAC THENL
705 [ASM_MESON_TAC[PERMUTES_COMPOSE];
706 DISCH_TAC THEN EXISTS_TAC `inverse(q:A->A) o (p:A->A)` THEN
707 ASM_SIMP_TAC[o_ASSOC; PERMUTES_INVERSE; PERMUTES_COMPOSE] THEN
708 ASM_MESON_TAC[PERMUTES_INVERSES_o; I_O_ID]]);;
710 let IMAGE_COMPOSE_PERMUTATIONS_R = prove
711 (`!s q:A->A. q permutes s ==> {p o q | p permutes s} = {p | p permutes s}`,
712 REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
713 X_GEN_TAC `p:A->A` THEN EQ_TAC THENL
714 [ASM_MESON_TAC[PERMUTES_COMPOSE];
715 DISCH_TAC THEN EXISTS_TAC `(p:A->A) o inverse(q:A->A)` THEN
716 ASM_SIMP_TAC[GSYM o_ASSOC; PERMUTES_INVERSE; PERMUTES_COMPOSE] THEN
717 ASM_MESON_TAC[PERMUTES_INVERSES_o; I_O_ID]]);;
719 let PERMUTES_IN_NUMSEG = prove
720 (`!p n i. p permutes 1..n /\ i IN 1..n ==> 1 <= p(i) /\ p(i) <= n`,
721 REWRITE_TAC[permutes; IN_NUMSEG] THEN MESON_TAC[]);;
723 let SUM_PERMUTATIONS_INVERSE = prove
724 (`!f m n. sum {p | p permutes m..n} f =
725 sum {p | p permutes m..n} (\p. f(inverse p))`,
727 GEN_REWRITE_TAC (funpow 2 LAND_CONV) [GSYM IMAGE_INVERSE_PERMUTATIONS] THEN
728 GEN_REWRITE_TAC (funpow 2 LAND_CONV)
729 [SET_RULE `{f x | p x} = IMAGE f {x | p x}`] THEN
730 GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
731 MATCH_MP_TAC SUM_IMAGE THEN
732 SIMP_TAC[FINITE_PERMUTATIONS; FINITE_NUMSEG; IN_ELIM_THM] THEN
733 MESON_TAC[PERMUTES_INVERSE_INVERSE]);;
735 let SUM_PERMUTATIONS_COMPOSE_L = prove
738 ==> sum {p | p permutes m..n} f =
739 sum {p | p permutes m..n} (\p. f(q o p))`,
740 REPEAT STRIP_TAC THEN
741 FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (funpow 2 LAND_CONV)
742 [GSYM(MATCH_MP IMAGE_COMPOSE_PERMUTATIONS_L th)]) THEN
743 GEN_REWRITE_TAC (funpow 2 LAND_CONV)
744 [SET_RULE `{f x | p x} = IMAGE f {x | p x}`] THEN
745 GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
746 MATCH_MP_TAC SUM_IMAGE THEN
747 SIMP_TAC[FINITE_PERMUTATIONS; FINITE_NUMSEG; IN_ELIM_THM] THEN
748 REPEAT STRIP_TAC THEN
749 FIRST_X_ASSUM(MP_TAC o AP_TERM `\p:num->num. inverse(q:num->num) o p`) THEN
750 REWRITE_TAC[o_ASSOC] THEN
751 EVERY_ASSUM(CONJUNCTS_THEN SUBST1_TAC o MATCH_MP PERMUTES_INVERSES_o) THEN
752 REWRITE_TAC[I_O_ID]);;
754 let SUM_PERMUTATIONS_COMPOSE_R = prove
757 ==> sum {p | p permutes m..n} f =
758 sum {p | p permutes m..n} (\p. f(p o q))`,
759 REPEAT STRIP_TAC THEN
760 FIRST_ASSUM(fun th -> GEN_REWRITE_TAC (funpow 2 LAND_CONV)
761 [GSYM(MATCH_MP IMAGE_COMPOSE_PERMUTATIONS_R th)]) THEN
762 GEN_REWRITE_TAC (funpow 2 LAND_CONV)
763 [SET_RULE `{f x | p x} = IMAGE f {x | p x}`] THEN
764 GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [GSYM o_DEF] THEN
765 MATCH_MP_TAC SUM_IMAGE THEN
766 SIMP_TAC[FINITE_PERMUTATIONS; FINITE_NUMSEG; IN_ELIM_THM] THEN
767 REPEAT STRIP_TAC THEN
768 FIRST_X_ASSUM(MP_TAC o AP_TERM `\p:num->num. p o inverse(q:num->num)`) THEN
769 REWRITE_TAC[GSYM o_ASSOC] THEN
770 EVERY_ASSUM(CONJUNCTS_THEN SUBST1_TAC o MATCH_MP PERMUTES_INVERSES_o) THEN
771 REWRITE_TAC[I_O_ID]);;
773 (* ------------------------------------------------------------------------- *)
774 (* Conversion for `{p | p permutes s}` where s is a set enumeration. *)
775 (* ------------------------------------------------------------------------- *)
778 let pth_empty = prove
779 (`{p | p permutes {}} = {I}`,
780 REWRITE_TAC[PERMUTES_EMPTY] THEN SET_TAC[])
781 and pth_cross = SET_RULE
782 `IMAGE f {x,y | x IN {} /\ y IN t} = {} /\
783 IMAGE f {x,y | x IN (a INSERT s) /\ y IN t} =
784 (IMAGE (\y. f(a,y)) t) UNION (IMAGE f {x,y | x IN s /\ y IN t})`
785 and pth_union = SET_RULE
787 (x INSERT s) UNION t = x INSERT (s UNION t)` in
788 let rec PERMSET_CONV tm =
789 (GEN_REWRITE_CONV I [pth_empty] ORELSEC
790 (GEN_REWRITE_CONV I [PERMUTES_INSERT] THENC
791 ONCE_DEPTH_CONV PERMSET_CONV THENC
792 REWRITE_CONV[pth_cross] THENC
793 REWRITE_CONV[IMAGE_CLAUSES] THENC
794 REWRITE_CONV[pth_union] THENC
795 REWRITE_CONV[SWAP_REFL; I_O_ID])) tm in
798 (* ------------------------------------------------------------------------- *)
799 (* Sum over a set of permutations (could generalize to iteration). *)
800 (* ------------------------------------------------------------------------- *)
802 let SUM_OVER_PERMUTATIONS_INSERT = prove
803 (`!f a s. FINITE s /\ ~(a IN s)
804 ==> sum {p:A->A | p permutes (a INSERT s)} f =
806 (\b. sum {p | p permutes s} (\q. f(swap(a,b) o q)))`,
808 (`(\(b,p). f (swap (a,b) o p)) = f o (\(b,p). swap(a,b) o p)`,
809 REWRITE_TAC[FUN_EQ_THM; FORALL_PAIR_THM; o_THM]) in
810 REPEAT STRIP_TAC THEN REWRITE_TAC[PERMUTES_INSERT] THEN
811 ASM_SIMP_TAC[FINITE_PERMUTATIONS; FINITE_INSERT; SUM_SUM_PRODUCT] THEN
812 REWRITE_TAC[lemma] THEN MATCH_MP_TAC SUM_IMAGE THEN
813 REWRITE_TAC[FORALL_PAIR_THM; IN_ELIM_PAIR_THM] THEN
814 REWRITE_TAC[IN_ELIM_THM] THEN
815 MAP_EVERY X_GEN_TAC [`b:A`; `p:A->A`; `c:A`; `q:A->A`] THEN
816 REPEAT STRIP_TAC THEN REWRITE_TAC[PAIR_EQ] THEN
817 MATCH_MP_TAC(TAUT `p /\ (p ==> q) ==> p /\ q`) THEN CONJ_TAC THENL
818 [FIRST_X_ASSUM(MP_TAC o C AP_THM `a:A`) THEN
819 REWRITE_TAC[o_THM; swap] THEN ASM_MESON_TAC[permutes];
820 DISCH_THEN SUBST_ALL_TAC THEN
821 FIRST_X_ASSUM(MP_TAC o AP_TERM `(\p:A->A. swap(a:A,c) o p)`) THEN
822 REWRITE_TAC[o_ASSOC; SWAP_IDEMPOTENT; I_O_ID]]);;
824 let SUM_OVER_PERMUTATIONS_NUMSEG = prove
826 ==> sum {p | p permutes (m..n)} f =
827 sum(m..n) (\i. sum {p | p permutes (m+1..n)}
828 (\q. f(swap(m,i) o q)))`,
829 REPEAT STRIP_TAC THEN ASM_SIMP_TAC[GSYM NUMSEG_LREC] THEN
830 MATCH_MP_TAC SUM_OVER_PERMUTATIONS_INSERT THEN
831 REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN ARITH_TAC);;