1 (* Title: HOL/Finite_Set.thy
2 Author: Tobias Nipkow, Lawrence C Paulson and Markus Wenzel
3 with contributions by Jeremy Avigad
6 header {* Finite sets *}
9 imports Nat Product_Type Power
12 subsection {* Definition and basic properties *}
14 inductive finite :: "'a set => bool"
16 emptyI [simp, intro!]: "finite {}"
17 | insertI [simp, intro!]: "finite A ==> finite (insert a A)"
19 lemma ex_new_if_finite: -- "does not depend on def of finite at all"
20 assumes "\<not> finite (UNIV :: 'a set)" and "finite A"
21 shows "\<exists>a::'a. a \<notin> A"
23 from assms have "A \<noteq> UNIV" by blast
27 lemma finite_induct [case_names empty insert, induct set: finite]:
29 P {} ==> (!!x F. finite F ==> x \<notin> F ==> P F ==> P (insert x F)) ==> P F"
30 -- {* Discharging @{text "x \<notin> F"} entails extra work. *}
33 insert: "!!x F. finite F ==> x \<notin> F ==> P F ==> P (insert x F)"
38 fix x F assume F: "finite F" and P: "P F"
42 hence "insert x F = F" by (rule insert_absorb)
43 with P show ?thesis by (simp only:)
46 from F this P show ?thesis by (rule insert)
51 lemma finite_ne_induct[case_names singleton insert, consumes 2]:
52 assumes fin: "finite F" shows "F \<noteq> {} \<Longrightarrow>
53 \<lbrakk> \<And>x. P{x};
54 \<And>x F. \<lbrakk> finite F; F \<noteq> {}; x \<notin> F; P F \<rbrakk> \<Longrightarrow> P (insert x F) \<rbrakk>
55 \<Longrightarrow> P F"
58 case empty thus ?case by simp
64 thus ?thesis using `P {x}` by simp
66 assume "F \<noteq> {}"
67 thus ?thesis using insert by blast
71 lemma finite_subset_induct [consumes 2, case_names empty insert]:
72 assumes "finite F" and "F \<subseteq> A"
74 and insert: "!!a F. finite F ==> a \<in> A ==> a \<notin> F ==> P F ==> P (insert a F)"
77 from `finite F` and `F \<subseteq> A`
83 assume "finite F" and "x \<notin> F" and
84 P: "F \<subseteq> A ==> P F" and i: "insert x F \<subseteq> A"
87 from i show "x \<in> A" by blast
88 from i have "F \<subseteq> A" by blast
90 show "finite F" by fact
91 show "x \<notin> F" by fact
96 text{* A finite choice principle. Does not need the SOME choice operator. *}
97 lemma finite_set_choice:
98 "finite A \<Longrightarrow> ALL x:A. (EX y. P x y) \<Longrightarrow> EX f. ALL x:A. P x (f x)"
99 proof (induct set: finite)
100 case empty thus ?case by simp
103 then obtain f b where f: "ALL x:A. P x (f x)" and ab: "P a b" by auto
104 show ?case (is "EX f. ?P f")
106 show "?P(%x. if x = a then b else f x)" using f ab by auto
111 text{* Finite sets are the images of initial segments of natural numbers: *}
113 lemma finite_imp_nat_seg_image_inj_on:
114 assumes fin: "finite A"
115 shows "\<exists> (n::nat) f. A = f ` {i. i<n} & inj_on f {i. i<n}"
120 proof show "\<exists>f. {} = f ` {i::nat. i < 0} & inj_on f {i. i<0}" by simp
124 have notinA: "a \<notin> A" by fact
125 from insert.hyps obtain n f
126 where "A = f ` {i::nat. i < n}" "inj_on f {i. i < n}" by blast
127 hence "insert a A = f(n:=a) ` {i. i < Suc n}"
128 "inj_on (f(n:=a)) {i. i < Suc n}" using notinA
129 by (auto simp add: image_def Ball_def inj_on_def less_Suc_eq)
133 lemma nat_seg_image_imp_finite:
134 "!!f A. A = f ` {i::nat. i<n} \<Longrightarrow> finite A"
136 case 0 thus ?case by simp
139 let ?B = "f ` {i. i < n}"
140 have finB: "finite ?B" by(rule Suc.hyps[OF refl])
143 assume "\<exists>k<n. f n = f k"
144 hence "A = ?B" using Suc.prems by(auto simp:less_Suc_eq)
145 thus ?thesis using finB by simp
147 assume "\<not>(\<exists> k<n. f n = f k)"
148 hence "A = insert (f n) ?B" using Suc.prems by(auto simp:less_Suc_eq)
149 thus ?thesis using finB by simp
153 lemma finite_conv_nat_seg_image:
154 "finite A = (\<exists> (n::nat) f. A = f ` {i::nat. i<n})"
155 by(blast intro: nat_seg_image_imp_finite dest: finite_imp_nat_seg_image_inj_on)
157 lemma finite_Collect_less_nat[iff]: "finite{n::nat. n<k}"
158 by(fastsimp simp: finite_conv_nat_seg_image)
161 subsubsection{* Finiteness and set theoretic constructions *}
163 lemma finite_UnI: "finite F ==> finite G ==> finite (F Un G)"
164 by (induct set: finite) simp_all
166 lemma finite_subset: "A \<subseteq> B ==> finite B ==> finite A"
167 -- {* Every subset of a finite set is finite. *}
170 thus "!!A. A \<subseteq> B ==> finite A"
176 have A: "A \<subseteq> insert x F" and r: "A - {x} \<subseteq> F ==> finite (A - {x})" by fact+
179 assume x: "x \<in> A"
180 with A have "A - {x} \<subseteq> F" by (simp add: subset_insert_iff)
181 with r have "finite (A - {x})" .
182 hence "finite (insert x (A - {x}))" ..
183 also have "insert x (A - {x}) = A" using x by (rule insert_Diff)
184 finally show ?thesis .
186 show "A \<subseteq> F ==> ?thesis" by fact
187 assume "x \<notin> A"
188 with A show "A \<subseteq> F" by (simp add: subset_insert_iff)
193 lemma finite_Un [iff]: "finite (F Un G) = (finite F & finite G)"
194 by (blast intro: finite_subset [of _ "X Un Y", standard] finite_UnI)
196 lemma finite_Collect_disjI[simp]:
197 "finite{x. P x | Q x} = (finite{x. P x} & finite{x. Q x})"
198 by(simp add:Collect_disj_eq)
200 lemma finite_Int [simp, intro]: "finite F | finite G ==> finite (F Int G)"
201 -- {* The converse obviously fails. *}
202 by (blast intro: finite_subset)
204 lemma finite_Collect_conjI [simp, intro]:
205 "finite{x. P x} | finite{x. Q x} ==> finite{x. P x & Q x}"
206 -- {* The converse obviously fails. *}
207 by(simp add:Collect_conj_eq)
209 lemma finite_Collect_le_nat[iff]: "finite{n::nat. n<=k}"
210 by(simp add: le_eq_less_or_eq)
212 lemma finite_insert [simp]: "finite (insert a A) = finite A"
213 apply (subst insert_is_Un)
214 apply (simp only: finite_Un, blast)
217 lemma finite_Union[simp, intro]:
218 "\<lbrakk> finite A; !!M. M \<in> A \<Longrightarrow> finite M \<rbrakk> \<Longrightarrow> finite(\<Union>A)"
219 by (induct rule:finite_induct) simp_all
221 lemma finite_empty_induct:
224 and "!!a A. finite A ==> a:A ==> P A ==> P (A - {a})"
231 assume c: "finite c" and b: "finite b"
232 and P1: "P b" and P2: "!!x y. finite y ==> x \<in> y ==> P y ==> P (y - {x})"
233 have "c \<subseteq> b ==> P (b - c)"
237 from P1 show ?case by simp
240 have "P (b - F - {x})"
242 from _ b show "finite (b - F)" by (rule finite_subset) blast
243 from insert show "x \<in> b - F" by simp
244 from insert show "P (b - F)" by simp
246 also have "b - F - {x} = b - insert x F" by (rule Diff_insert [symmetric])
250 then show ?thesis by this (simp_all add: assms)
252 then show ?thesis by simp
255 lemma finite_Diff [simp]: "finite A ==> finite (A - B)"
256 by (rule Diff_subset [THEN finite_subset])
258 lemma finite_Diff2 [simp]:
259 assumes "finite B" shows "finite (A - B) = finite A"
261 have "finite A \<longleftrightarrow> finite((A-B) Un (A Int B))" by(simp add: Un_Diff_Int)
262 also have "\<dots> \<longleftrightarrow> finite(A-B)" using `finite B` by(simp)
263 finally show ?thesis ..
266 lemma finite_compl[simp]:
267 "finite(A::'a set) \<Longrightarrow> finite(-A) = finite(UNIV::'a set)"
268 by(simp add:Compl_eq_Diff_UNIV)
270 lemma finite_Collect_not[simp]:
271 "finite{x::'a. P x} \<Longrightarrow> finite{x. ~P x} = finite(UNIV::'a set)"
272 by(simp add:Collect_neg_eq)
274 lemma finite_Diff_insert [iff]: "finite (A - insert a B) = finite (A - B)"
275 apply (subst Diff_insert)
276 apply (case_tac "a : A - B")
277 apply (rule finite_insert [symmetric, THEN trans])
278 apply (subst insert_Diff, simp_all)
282 text {* Image and Inverse Image over Finite Sets *}
284 lemma finite_imageI[simp]: "finite F ==> finite (h ` F)"
285 -- {* The image of a finite set is finite. *}
286 by (induct set: finite) simp_all
288 lemma finite_surj: "finite A ==> B <= f ` A ==> finite B"
289 apply (frule finite_imageI)
290 apply (erule finite_subset, assumption)
293 lemma finite_range_imageI:
294 "finite (range g) ==> finite (range (%x. f (g x)))"
295 apply (drule finite_imageI, simp add: range_composition)
298 lemma finite_imageD: "finite (f`A) ==> inj_on f A ==> finite A"
300 have aux: "!!A. finite (A - {}) = finite A" by simp
303 thus "!!A. f`A = B ==> inj_on f A ==> finite A"
306 apply (subgoal_tac "EX y:A. f y = x & F = f ` (A - {y})")
308 apply (simp (no_asm_use) add: inj_on_def)
309 apply (blast dest!: aux [THEN iffD1], atomize)
310 apply (erule_tac V = "ALL A. ?PP (A)" in thin_rl)
311 apply (frule subsetD [OF equalityD2 insertI1], clarify)
312 apply (rule_tac x = xa in bexI)
313 apply (simp_all add: inj_on_image_set_diff)
318 lemma inj_vimage_singleton: "inj f ==> f-`{a} \<subseteq> {THE x. f x = a}"
319 -- {* The inverse image of a singleton under an injective function
320 is included in a singleton. *}
321 apply (auto simp add: inj_on_def)
322 apply (blast intro: the_equality [symmetric])
325 lemma finite_vimageI: "[|finite F; inj h|] ==> finite (h -` F)"
326 -- {* The inverse image of a finite set under an injective function
328 apply (induct set: finite)
330 apply (subst vimage_insert)
331 apply (simp add: finite_Un finite_subset [OF inj_vimage_singleton])
335 text {* The finite UNION of finite sets *}
337 lemma finite_UN_I: "finite A ==> (!!a. a:A ==> finite (B a)) ==> finite (UN a:A. B a)"
338 by (induct set: finite) simp_all
342 @{prop "((ALL x:A. finite (B x)) & finite {x. x:A & B x \<noteq> {}})"}?
345 @{prop "finite C ==> ALL A B. (UNION A B) <= C --> finite {x. x:A & B x \<noteq> {}}"}
348 lemma finite_UN [simp]:
349 "finite A ==> finite (UNION A B) = (ALL x:A. finite (B x))"
350 by (blast intro: finite_UN_I finite_subset)
352 lemma finite_Collect_bex[simp]: "finite A \<Longrightarrow>
353 finite{x. EX y:A. Q x y} = (ALL y:A. finite{x. Q x y})"
354 apply(subgoal_tac "{x. EX y:A. Q x y} = UNION A (%y. {x. Q x y})")
358 lemma finite_Collect_bounded_ex[simp]: "finite{y. P y} \<Longrightarrow>
359 finite{x. EX y. P y & Q x y} = (ALL y. P y \<longrightarrow> finite{x. Q x y})"
360 apply(subgoal_tac "{x. EX y. P y & Q x y} = UNION {y. P y} (%y. {x. Q x y})")
365 lemma finite_Plus: "[| finite A; finite B |] ==> finite (A <+> B)"
366 by (simp add: Plus_def)
368 text {* Sigma of finite sets *}
370 lemma finite_SigmaI [simp]:
371 "finite A ==> (!!a. a:A ==> finite (B a)) ==> finite (SIGMA a:A. B a)"
372 by (unfold Sigma_def) (blast intro!: finite_UN_I)
374 lemma finite_cartesian_product: "[| finite A; finite B |] ==>
376 by (rule finite_SigmaI)
378 lemma finite_Prod_UNIV:
379 "finite (UNIV::'a set) ==> finite (UNIV::'b set) ==> finite (UNIV::('a * 'b) set)"
380 apply (subgoal_tac "(UNIV:: ('a * 'b) set) = Sigma UNIV (%x. UNIV)")
382 apply (erule finite_SigmaI, auto)
385 lemma finite_cartesian_productD1:
386 "[| finite (A <*> B); B \<noteq> {} |] ==> finite A"
387 apply (auto simp add: finite_conv_nat_seg_image)
388 apply (drule_tac x=n in spec)
389 apply (drule_tac x="fst o f" in spec)
390 apply (auto simp add: o_def)
391 prefer 2 apply (force dest!: equalityD2)
392 apply (drule equalityD1)
393 apply (rename_tac y x)
394 apply (subgoal_tac "\<exists>k. k<n & f k = (x,y)")
397 apply (rule_tac x=k in image_eqI, auto)
400 lemma finite_cartesian_productD2:
401 "[| finite (A <*> B); A \<noteq> {} |] ==> finite B"
402 apply (auto simp add: finite_conv_nat_seg_image)
403 apply (drule_tac x=n in spec)
404 apply (drule_tac x="snd o f" in spec)
405 apply (auto simp add: o_def)
406 prefer 2 apply (force dest!: equalityD2)
407 apply (drule equalityD1)
408 apply (rename_tac x y)
409 apply (subgoal_tac "\<exists>k. k<n & f k = (x,y)")
412 apply (rule_tac x=k in image_eqI, auto)
416 text {* The powerset of a finite set *}
418 lemma finite_Pow_iff [iff]: "finite (Pow A) = finite A"
420 assume "finite (Pow A)"
421 with _ have "finite ((%x. {x}) ` A)" by (rule finite_subset) blast
422 thus "finite A" by (rule finite_imageD [unfolded inj_on_def]) simp
425 thus "finite (Pow A)"
426 by induct (simp_all add: finite_UnI finite_imageI Pow_insert)
429 lemma finite_Collect_subsets[simp,intro]: "finite A \<Longrightarrow> finite{B. B \<subseteq> A}"
430 by(simp add: Pow_def[symmetric])
433 lemma finite_UnionD: "finite(\<Union>A) \<Longrightarrow> finite A"
434 by(blast intro: finite_subset[OF subset_Pow_Union])
437 subsection {* Class @{text finite} *}
439 setup {* Sign.add_path "finite" *} -- {*FIXME: name tweaking*}
441 assumes finite_UNIV: "finite (UNIV \<Colon> 'a set)"
442 setup {* Sign.parent_path *}
448 lemma finite [simp]: "finite (A \<Colon> 'a set)"
449 by (rule subset_UNIV finite_UNIV finite_subset)+
453 lemma UNIV_unit [noatp]:
454 "UNIV = {()}" by auto
456 instance unit :: finite
457 by default (simp add: UNIV_unit)
459 lemma UNIV_bool [noatp]:
460 "UNIV = {False, True}" by auto
462 instance bool :: finite
463 by default (simp add: UNIV_bool)
465 instance * :: (finite, finite) finite
466 by default (simp only: UNIV_Times_UNIV [symmetric] finite_cartesian_product finite)
468 lemma inj_graph: "inj (%f. {(x, y). y = f x})"
469 by (rule inj_onI, auto simp add: expand_set_eq expand_fun_eq)
471 instance "fun" :: (finite, finite) finite
473 show "finite (UNIV :: ('a => 'b) set)"
474 proof (rule finite_imageD)
475 let ?graph = "%f::'a => 'b. {(x, y). y = f x}"
476 have "range ?graph \<subseteq> Pow UNIV" by simp
477 moreover have "finite (Pow (UNIV :: ('a * 'b) set))"
478 by (simp only: finite_Pow_iff finite)
479 ultimately show "finite (range ?graph)"
480 by (rule finite_subset)
481 show "inj ?graph" by (rule inj_graph)
485 instance "+" :: (finite, finite) finite
486 by default (simp only: UNIV_Plus_UNIV [symmetric] finite_Plus finite)
489 subsection {* A fold functional for finite sets *}
491 text {* The intended behaviour is
492 @{text "fold f z {x\<^isub>1, ..., x\<^isub>n} = f x\<^isub>1 (\<dots> (f x\<^isub>n z)\<dots>)"}
493 if @{text f} is ``left-commutative'':
496 locale fun_left_comm =
497 fixes f :: "'a \<Rightarrow> 'b \<Rightarrow> 'b"
498 assumes fun_left_comm: "f x (f y z) = f y (f x z)"
501 text{* On a functional level it looks much nicer: *}
503 lemma fun_comp_comm: "f x \<circ> f y = f y \<circ> f x"
504 by (simp add: fun_left_comm expand_fun_eq)
508 inductive fold_graph :: "('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a set \<Rightarrow> 'b \<Rightarrow> bool"
509 for f :: "'a \<Rightarrow> 'b \<Rightarrow> 'b" and z :: 'b where
510 emptyI [intro]: "fold_graph f z {} z" |
511 insertI [intro]: "x \<notin> A \<Longrightarrow> fold_graph f z A y
512 \<Longrightarrow> fold_graph f z (insert x A) (f x y)"
514 inductive_cases empty_fold_graphE [elim!]: "fold_graph f z {} x"
516 definition fold :: "('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a set \<Rightarrow> 'b" where
517 [code del]: "fold f z A = (THE y. fold_graph f z A y)"
519 text{*A tempting alternative for the definiens is
520 @{term "if finite A then THE y. fold_graph f z A y else e"}.
521 It allows the removal of finiteness assumptions from the theorems
522 @{text fold_comm}, @{text fold_reindex} and @{text fold_distrib}.
523 The proofs become ugly. It is not worth the effort. (???) *}
526 lemma Diff1_fold_graph:
527 "fold_graph f z (A - {x}) y \<Longrightarrow> x \<in> A \<Longrightarrow> fold_graph f z A (f x y)"
528 by (erule insert_Diff [THEN subst], rule fold_graph.intros, auto)
530 lemma fold_graph_imp_finite: "fold_graph f z A x \<Longrightarrow> finite A"
531 by (induct set: fold_graph) auto
533 lemma finite_imp_fold_graph: "finite A \<Longrightarrow> \<exists>x. fold_graph f z A x"
534 by (induct set: finite) auto
537 subsubsection{*From @{const fold_graph} to @{term fold}*}
539 lemma image_less_Suc: "h ` {i. i < Suc m} = insert (h m) (h ` {i. i < m})"
540 by (auto simp add: less_Suc_eq)
542 lemma insert_image_inj_on_eq:
543 "[|insert (h m) A = h ` {i. i < Suc m}; h m \<notin> A;
544 inj_on h {i. i < Suc m}|]
545 ==> A = h ` {i. i < m}"
546 apply (auto simp add: image_less_Suc inj_on_def)
547 apply (blast intro: less_trans)
550 lemma insert_inj_onE:
551 assumes aA: "insert a A = h`{i::nat. i<n}" and anot: "a \<notin> A"
552 and inj_on: "inj_on h {i::nat. i<n}"
553 shows "\<exists>hm m. inj_on hm {i::nat. i<m} & A = hm ` {i. i<m} & m < n"
555 case 0 thus ?thesis using aA by auto
558 have nSuc: "n = Suc m" by fact
559 have mlessn: "m<n" by (simp add: nSuc)
560 from aA obtain k where hkeq: "h k = a" and klessn: "k<n" by (blast elim!: equalityE)
561 let ?hm = "Fun.swap k m h"
562 have inj_hm: "inj_on ?hm {i. i < n}" using klessn mlessn
563 by (simp add: inj_on_swap_iff inj_on)
565 proof (intro exI conjI)
566 show "inj_on ?hm {i. i < m}" using inj_hm
567 by (auto simp add: nSuc less_Suc_eq intro: subset_inj_on)
568 show "m<n" by (rule mlessn)
569 show "A = ?hm ` {i. i < m}"
570 proof (rule insert_image_inj_on_eq)
571 show "inj_on (Fun.swap k m h) {i. i < Suc m}" using inj_hm nSuc by simp
572 show "?hm m \<notin> A" by (simp add: swap_def hkeq anot)
573 show "insert (?hm m) A = ?hm ` {i. i < Suc m}"
574 using aA hkeq nSuc klessn
575 by (auto simp add: swap_def image_less_Suc fun_upd_image
576 less_Suc_eq inj_on_image_set_diff [OF inj_on])
581 context fun_left_comm
584 lemma fold_graph_determ_aux:
585 "A = h`{i::nat. i<n} \<Longrightarrow> inj_on h {i. i<n}
586 \<Longrightarrow> fold_graph f z A x \<Longrightarrow> fold_graph f z A x'
587 \<Longrightarrow> x' = x"
588 proof (induct n arbitrary: A x x' h rule: less_induct)
590 have IH: "\<And>m h A x x'. m < n \<Longrightarrow> A = h ` {i. i<m}
591 \<Longrightarrow> inj_on h {i. i<m} \<Longrightarrow> fold_graph f z A x
592 \<Longrightarrow> fold_graph f z A x' \<Longrightarrow> x' = x" by fact
593 have Afoldx: "fold_graph f z A x" and Afoldx': "fold_graph f z A x'"
594 and A: "A = h`{i. i<n}" and injh: "inj_on h {i. i<n}" by fact+
596 proof (rule fold_graph.cases [OF Afoldx])
597 assume "A = {}" and "x = z"
598 with Afoldx' show "x' = x" by auto
601 assume AbB: "A = insert b B" and x: "x = f b u"
602 and notinB: "b \<notin> B" and Bu: "fold_graph f z B u"
604 proof (rule fold_graph.cases [OF Afoldx'])
605 assume "A = {}" and "x' = z"
606 with AbB show "x' = x" by blast
609 assume AcC: "A = insert c C" and x': "x' = f c v"
610 and notinC: "c \<notin> C" and Cv: "fold_graph f z C v"
611 from A AbB have Beq: "insert b B = h`{i. i<n}" by simp
612 from insert_inj_onE [OF Beq notinB injh]
613 obtain hB mB where inj_onB: "inj_on hB {i. i < mB}"
614 and Beq: "B = hB ` {i. i < mB}" and lessB: "mB < n" by auto
615 from A AcC have Ceq: "insert c C = h`{i. i<n}" by simp
616 from insert_inj_onE [OF Ceq notinC injh]
617 obtain hC mC where inj_onC: "inj_on hC {i. i < mC}"
618 and Ceq: "C = hC ` {i. i < mC}" and lessC: "mC < n" by auto
622 then moreover have "B = C" using AbB AcC notinB notinC by auto
623 ultimately show ?thesis using Bu Cv x x' IH [OF lessC Ceq inj_onC]
626 assume diff: "b \<noteq> c"
628 have B: "B = insert c ?D" and C: "C = insert b ?D"
629 using AbB AcC notinB notinC diff by(blast elim!:equalityE)+
630 have "finite A" by(rule fold_graph_imp_finite [OF Afoldx])
631 with AbB have "finite ?D" by simp
632 then obtain d where Dfoldd: "fold_graph f z ?D d"
633 using finite_imp_fold_graph by iprover
634 moreover have cinB: "c \<in> B" using B by auto
635 ultimately have "fold_graph f z B (f c d)" by(rule Diff1_fold_graph)
636 hence "f c d = u" by (rule IH [OF lessB Beq inj_onB Bu])
637 moreover have "f b d = v"
638 proof (rule IH[OF lessC Ceq inj_onC Cv])
639 show "fold_graph f z C (f b d)" using C notinB Dfoldd by fastsimp
641 ultimately show ?thesis
642 using fun_left_comm [of c b] x x' by (auto simp add: o_def)
648 lemma fold_graph_determ:
649 "fold_graph f z A x \<Longrightarrow> fold_graph f z A y \<Longrightarrow> y = x"
650 apply (frule fold_graph_imp_finite [THEN finite_imp_nat_seg_image_inj_on])
651 apply (blast intro: fold_graph_determ_aux [rule_format])
655 "fold_graph f z A y \<Longrightarrow> fold f z A = y"
656 by (unfold fold_def) (blast intro: fold_graph_determ)
658 text{* The base case for @{text fold}: *}
660 lemma (in -) fold_empty [simp]: "fold f z {} = z"
661 by (unfold fold_def) blast
663 text{* The various recursion equations for @{const fold}: *}
665 lemma fold_insert_aux: "x \<notin> A
666 \<Longrightarrow> fold_graph f z (insert x A) v \<longleftrightarrow>
667 (\<exists>y. fold_graph f z A y \<and> v = f x y)"
669 apply (rule_tac A1 = A and f1 = f in finite_imp_fold_graph [THEN exE])
670 apply (fastsimp dest: fold_graph_imp_finite)
671 apply (blast intro: fold_graph_determ)
674 lemma fold_insert [simp]:
675 "finite A ==> x \<notin> A ==> fold f z (insert x A) = f x (fold f z A)"
676 apply (simp add: fold_def fold_insert_aux)
677 apply (rule the_equality)
678 apply (auto intro: finite_imp_fold_graph
679 cong add: conj_cong simp add: fold_def[symmetric] fold_equality)
683 "finite A \<Longrightarrow> f x (fold f z A) = fold f (f x z) A"
684 proof (induct rule: finite_induct)
685 case empty then show ?case by simp
687 case (insert y A) then show ?case
688 by (simp add: fun_left_comm[of x])
692 "finite A \<Longrightarrow> x \<notin> A \<Longrightarrow> fold f z (insert x A) = fold f (f x z) A"
693 by (simp add: fold_insert fold_fun_comm)
696 assumes "finite A" and "x \<in> A"
697 shows "fold f z A = f x (fold f z (A - {x}))"
699 have A: "A = insert x (A - {x})" using `x \<in> A` by blast
700 then have "fold f z A = fold f z (insert x (A - {x}))" by simp
701 also have "\<dots> = f x (fold f z (A - {x}))"
702 by (rule fold_insert) (simp add: `finite A`)+
703 finally show ?thesis .
706 lemma fold_insert_remove:
708 shows "fold f z (insert x A) = f x (fold f z (A - {x}))"
710 from `finite A` have "finite (insert x A)" by auto
711 moreover have "x \<in> insert x A" by auto
712 ultimately have "fold f z (insert x A) = f x (fold f z (insert x A - {x}))"
714 then show ?thesis by simp
719 text{* A simplified version for idempotent functions: *}
721 locale fun_left_comm_idem = fun_left_comm +
722 assumes fun_left_idem: "f x (f x z) = f x z"
725 text{* The nice version: *}
726 lemma fun_comp_idem : "f x o f x = f x"
727 by (simp add: fun_left_idem expand_fun_eq)
729 lemma fold_insert_idem:
730 assumes fin: "finite A"
731 shows "fold f z (insert x A) = f x (fold f z A)"
734 then obtain B where "A = insert x B" and "x \<notin> B" by (rule set_insert)
735 then show ?thesis using assms by (simp add:fun_left_idem)
737 assume "x \<notin> A" then show ?thesis using assms by simp
740 declare fold_insert[simp del] fold_insert_idem[simp]
742 lemma fold_insert_idem2:
743 "finite A \<Longrightarrow> fold f z (insert x A) = fold f (f x z) A"
744 by(simp add:fold_fun_comm)
748 subsubsection{* The derived combinator @{text fold_image} *}
750 definition fold_image :: "('b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a set \<Rightarrow> 'b"
751 where "fold_image f g = fold (%x y. f (g x) y)"
753 lemma fold_image_empty[simp]: "fold_image f g z {} = z"
754 by(simp add:fold_image_def)
756 context ab_semigroup_mult
759 lemma fold_image_insert[simp]:
760 assumes "finite A" and "a \<notin> A"
761 shows "fold_image times g z (insert a A) = g a * (fold_image times g z A)"
763 interpret I: fun_left_comm "%x y. (g x) * y"
764 by unfold_locales (simp add: mult_ac)
765 show ?thesis using assms by(simp add:fold_image_def I.fold_insert)
770 "finite A ==> (!!z. x * (fold times g z A) = fold times g (x * z) A)"
771 apply (induct set: finite)
773 apply (simp add: mult_left_commute [of x])
776 lemma fold_nest_Un_Int:
777 "finite A ==> finite B
778 ==> fold times g (fold times g z B) A = fold times g (fold times g z (A Int B)) (A Un B)"
779 apply (induct set: finite)
781 apply (simp add: fold_commute Int_insert_left insert_absorb)
784 lemma fold_nest_Un_disjoint:
785 "finite A ==> finite B ==> A Int B = {}
786 ==> fold times g z (A Un B) = fold times g (fold times g z B) A"
787 by (simp add: fold_nest_Un_Int)
790 lemma fold_image_reindex:
791 assumes fin: "finite A"
792 shows "inj_on h A \<Longrightarrow> fold_image times g z (h`A) = fold_image times (g\<circ>h) z A"
793 using fin apply induct
800 Fusion theorem, as described in Graham Hutton's paper,
801 A Tutorial on the Universality and Expressiveness of Fold,
802 JFP 9:4 (355-372), 1999.
806 assumes "ab_semigroup_mult g"
807 assumes fin: "finite A"
808 and hyp: "\<And>x y. h (g x y) = times x (h y)"
809 shows "h (fold g j w A) = fold times j (h w) A"
811 class_interpret ab_semigroup_mult [g] by fact
812 show ?thesis using fin hyp by (induct set: finite) simp_all
816 lemma fold_image_cong:
817 "finite A \<Longrightarrow>
818 (!!x. x:A ==> g x = h x) ==> fold_image times g z A = fold_image times h z A"
819 apply (subgoal_tac "ALL C. C <= A --> (ALL x:C. g x = h x) --> fold_image times g z C = fold_image times h z C")
821 apply (erule finite_induct, simp)
822 apply (simp add: subset_insert_iff, clarify)
823 apply (subgoal_tac "finite C")
824 prefer 2 apply (blast dest: finite_subset [COMP swap_prems_rl])
825 apply (subgoal_tac "C = insert x (C - {x})")
829 apply (erule (1) notE impE)
830 apply (simp add: Ball_def del: insert_Diff_single)
835 context comm_monoid_mult
838 lemma fold_image_Un_Int:
839 "finite A ==> finite B ==>
840 fold_image times g 1 A * fold_image times g 1 B =
841 fold_image times g 1 (A Un B) * fold_image times g 1 (A Int B)"
842 by (induct set: finite)
843 (auto simp add: mult_ac insert_absorb Int_insert_left)
845 corollary fold_Un_disjoint:
846 "finite A ==> finite B ==> A Int B = {} ==>
847 fold_image times g 1 (A Un B) =
848 fold_image times g 1 A * fold_image times g 1 B"
849 by (simp add: fold_image_Un_Int)
851 lemma fold_image_UN_disjoint:
852 "\<lbrakk> finite I; ALL i:I. finite (A i);
853 ALL i:I. ALL j:I. i \<noteq> j --> A i Int A j = {} \<rbrakk>
854 \<Longrightarrow> fold_image times g 1 (UNION I A) =
855 fold_image times (%i. fold_image times g 1 (A i)) 1 I"
856 apply (induct set: finite, simp, atomize)
857 apply (subgoal_tac "ALL i:F. x \<noteq> i")
859 apply (subgoal_tac "A x Int UNION F A = {}")
861 apply (simp add: fold_Un_disjoint)
864 lemma fold_image_Sigma: "finite A ==> ALL x:A. finite (B x) ==>
865 fold_image times (%x. fold_image times (g x) 1 (B x)) 1 A =
866 fold_image times (split g) 1 (SIGMA x:A. B x)"
867 apply (subst Sigma_def)
868 apply (subst fold_image_UN_disjoint, assumption, simp)
870 apply (erule fold_image_cong)
871 apply (subst fold_image_UN_disjoint, simp, simp)
876 lemma fold_image_distrib: "finite A \<Longrightarrow>
877 fold_image times (%x. g x * h x) 1 A =
878 fold_image times g 1 A * fold_image times h 1 A"
879 by (erule finite_induct) (simp_all add: mult_ac)
881 lemma fold_image_related:
883 and Rop: "\<forall>x1 y1 x2 y2. R x1 x2 \<and> R y1 y2 \<longrightarrow> R (x1 * y1) (x2 * y2)"
884 and fS: "finite S" and Rfg: "\<forall>x\<in>S. R (h x) (g x)"
885 shows "R (fold_image (op *) h e S) (fold_image (op *) g e S)"
886 using fS by (rule finite_subset_induct) (insert assms, auto)
888 lemma fold_image_eq_general:
889 assumes fS: "finite S"
890 and h: "\<forall>y\<in>S'. \<exists>!x. x\<in> S \<and> h(x) = y"
891 and f12: "\<forall>x\<in>S. h x \<in> S' \<and> f2(h x) = f1 x"
892 shows "fold_image (op *) f1 e S = fold_image (op *) f2 e S'"
894 from h f12 have hS: "h ` S = S'" by auto
895 {fix x y assume H: "x \<in> S" "y \<in> S" "h x = h y"
896 from f12 h H have "x = y" by auto }
897 hence hinj: "inj_on h S" unfolding inj_on_def Ex1_def by blast
898 from f12 have th: "\<And>x. x \<in> S \<Longrightarrow> (f2 \<circ> h) x = f1 x" by auto
899 from hS have "fold_image (op *) f2 e S' = fold_image (op *) f2 e (h ` S)" by simp
900 also have "\<dots> = fold_image (op *) (f2 o h) e S"
901 using fold_image_reindex[OF fS hinj, of f2 e] .
902 also have "\<dots> = fold_image (op *) f1 e S " using th fold_image_cong[OF fS, of "f2 o h" f1 e]
904 finally show ?thesis ..
907 lemma fold_image_eq_general_inverses:
908 assumes fS: "finite S"
909 and kh: "\<And>y. y \<in> T \<Longrightarrow> k y \<in> S \<and> h (k y) = y"
910 and hk: "\<And>x. x \<in> S \<Longrightarrow> h x \<in> T \<and> k (h x) = x \<and> g (h x) = f x"
911 shows "fold_image (op *) f e S = fold_image (op *) g e T"
912 (* metis solves it, but not yet available here *)
913 apply (rule fold_image_eq_general[OF fS, of T h g f e])
919 apply (drule hk) apply simp
921 apply (erule conjunct1[OF conjunct2[OF hk]])
929 subsection {* Generalized summation over a set *}
931 interpretation comm_monoid_add: comm_monoid_mult "0::'a::comm_monoid_add" "op +"
932 proof qed (auto intro: add_assoc add_commute)
934 definition setsum :: "('a => 'b) => 'a set => 'b::comm_monoid_add"
935 where "setsum f A == if finite A then fold_image (op +) f 0 A else 0"
938 Setsum ("\<Sum>_" [1000] 999) where
939 "\<Sum>A == setsum (%x. x) A"
941 text{* Now: lot's of fancy syntax. First, @{term "setsum (%x. e) A"} is
942 written @{text"\<Sum>x\<in>A. e"}. *}
945 "_setsum" :: "pttrn => 'a set => 'b => 'b::comm_monoid_add" ("(3SUM _:_. _)" [0, 51, 10] 10)
947 "_setsum" :: "pttrn => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_\<in>_. _)" [0, 51, 10] 10)
949 "_setsum" :: "pttrn => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_\<in>_. _)" [0, 51, 10] 10)
951 translations -- {* Beware of argument permutation! *}
952 "SUM i:A. b" == "CONST setsum (%i. b) A"
953 "\<Sum>i\<in>A. b" == "CONST setsum (%i. b) A"
955 text{* Instead of @{term"\<Sum>x\<in>{x. P}. e"} we introduce the shorter
956 @{text"\<Sum>x|P. e"}. *}
959 "_qsetsum" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3SUM _ |/ _./ _)" [0,0,10] 10)
961 "_qsetsum" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3\<Sum>_ | (_)./ _)" [0,0,10] 10)
963 "_qsetsum" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3\<Sum>_ | (_)./ _)" [0,0,10] 10)
966 "SUM x|P. t" => "CONST setsum (%x. t) {x. P}"
967 "\<Sum>x|P. t" => "CONST setsum (%x. t) {x. P}"
971 fun setsum_tr' [Abs(x,Tx,t), Const ("Collect",_) $ Abs(y,Ty,P)] =
972 if x<>y then raise Match
973 else let val x' = Syntax.mark_bound x
974 val t' = subst_bound(x',t)
975 val P' = subst_bound(x',P)
976 in Syntax.const "_qsetsum" $ Syntax.mark_bound x $ P' $ t' end
977 in [("setsum", setsum_tr')] end
981 lemma setsum_empty [simp]: "setsum f {} = 0"
982 by (simp add: setsum_def)
984 lemma setsum_insert [simp]:
985 "finite F ==> a \<notin> F ==> setsum f (insert a F) = f a + setsum f F"
986 by (simp add: setsum_def)
988 lemma setsum_infinite [simp]: "~ finite A ==> setsum f A = 0"
989 by (simp add: setsum_def)
991 lemma setsum_reindex:
992 "inj_on f B ==> setsum h (f ` B) = setsum (h \<circ> f) B"
993 by(auto simp add: setsum_def comm_monoid_add.fold_image_reindex dest!:finite_imageD)
995 lemma setsum_reindex_id:
996 "inj_on f B ==> setsum f B = setsum id (f ` B)"
997 by (auto simp add: setsum_reindex)
999 lemma setsum_reindex_nonzero:
1000 assumes fS: "finite S"
1001 and nz: "\<And> x y. x \<in> S \<Longrightarrow> y \<in> S \<Longrightarrow> x \<noteq> y \<Longrightarrow> f x = f y \<Longrightarrow> h (f x) = 0"
1002 shows "setsum h (f ` S) = setsum (h o f) S"
1004 proof(induct rule: finite_induct[OF fS])
1005 case 1 thus ?case by simp
1008 {assume fxF: "f x \<in> f ` F" hence "\<exists>y \<in> F . f y = f x" by auto
1009 then obtain y where y: "y \<in> F" "f x = f y" by auto
1010 from "2.hyps" y have xy: "x \<noteq> y" by auto
1012 from "2.prems"[of x y] "2.hyps" xy y have h0: "h (f x) = 0" by simp
1013 have "setsum h (f ` insert x F) = setsum h (f ` F)" using fxF by auto
1014 also have "\<dots> = setsum (h o f) (insert x F)"
1015 unfolding setsum_insert[OF `finite F` `x\<notin>F`]
1018 apply (rule "2.hyps"(3))
1019 apply (rule_tac y="y" in "2.prems")
1022 finally have ?case .}
1024 {assume fxF: "f x \<notin> f ` F"
1025 have "setsum h (f ` insert x F) = h (f x) + setsum h (f ` F)"
1026 using fxF "2.hyps" by simp
1027 also have "\<dots> = setsum (h o f) (insert x F)"
1028 unfolding setsum_insert[OF `finite F` `x\<notin>F`]
1030 apply (rule cong[OF refl[of "op + (h (f x))"]])
1031 apply (rule "2.hyps"(3))
1032 apply (rule_tac y="y" in "2.prems")
1035 finally have ?case .}
1036 ultimately show ?case by blast
1040 "A = B ==> (!!x. x:B ==> f x = g x) ==> setsum f A = setsum g B"
1041 by(fastsimp simp: setsum_def intro: comm_monoid_add.fold_image_cong)
1043 lemma strong_setsum_cong[cong]:
1044 "A = B ==> (!!x. x:B =simp=> f x = g x)
1045 ==> setsum (%x. f x) A = setsum (%x. g x) B"
1046 by(fastsimp simp: simp_implies_def setsum_def intro: comm_monoid_add.fold_image_cong)
1048 lemma setsum_cong2: "\<lbrakk>\<And>x. x \<in> A \<Longrightarrow> f x = g x\<rbrakk> \<Longrightarrow> setsum f A = setsum g A";
1049 by (rule setsum_cong[OF refl], auto);
1051 lemma setsum_reindex_cong:
1052 "[|inj_on f A; B = f ` A; !!a. a:A \<Longrightarrow> g a = h (f a)|]
1053 ==> setsum h B = setsum g A"
1054 by (simp add: setsum_reindex cong: setsum_cong)
1057 lemma setsum_0[simp]: "setsum (%i. 0) A = 0"
1058 apply (clarsimp simp: setsum_def)
1059 apply (erule finite_induct, auto)
1062 lemma setsum_0': "ALL a:A. f a = 0 ==> setsum f A = 0"
1063 by(simp add:setsum_cong)
1065 lemma setsum_Un_Int: "finite A ==> finite B ==>
1066 setsum g (A Un B) + setsum g (A Int B) = setsum g A + setsum g B"
1067 -- {* The reversed orientation looks more natural, but LOOPS as a simprule! *}
1068 by(simp add: setsum_def comm_monoid_add.fold_image_Un_Int [symmetric])
1070 lemma setsum_Un_disjoint: "finite A ==> finite B
1071 ==> A Int B = {} ==> setsum g (A Un B) = setsum g A + setsum g B"
1072 by (subst setsum_Un_Int [symmetric], auto)
1074 lemma setsum_mono_zero_left:
1075 assumes fT: "finite T" and ST: "S \<subseteq> T"
1076 and z: "\<forall>i \<in> T - S. f i = 0"
1077 shows "setsum f S = setsum f T"
1079 have eq: "T = S \<union> (T - S)" using ST by blast
1080 have d: "S \<inter> (T - S) = {}" using ST by blast
1081 from fT ST have f: "finite S" "finite (T - S)" by (auto intro: finite_subset)
1083 by (simp add: setsum_Un_disjoint[OF f d, unfolded eq[symmetric]] setsum_0'[OF z])
1086 lemma setsum_mono_zero_right:
1087 "finite T \<Longrightarrow> S \<subseteq> T \<Longrightarrow> \<forall>i \<in> T - S. f i = 0 \<Longrightarrow> setsum f T = setsum f S"
1088 by(blast intro!: setsum_mono_zero_left[symmetric])
1090 lemma setsum_mono_zero_cong_left:
1091 assumes fT: "finite T" and ST: "S \<subseteq> T"
1092 and z: "\<forall>i \<in> T - S. g i = 0"
1093 and fg: "\<And>x. x \<in> S \<Longrightarrow> f x = g x"
1094 shows "setsum f S = setsum g T"
1096 have eq: "T = S \<union> (T - S)" using ST by blast
1097 have d: "S \<inter> (T - S) = {}" using ST by blast
1098 from fT ST have f: "finite S" "finite (T - S)" by (auto intro: finite_subset)
1100 using fg by (simp add: setsum_Un_disjoint[OF f d, unfolded eq[symmetric]] setsum_0'[OF z])
1103 lemma setsum_mono_zero_cong_right:
1104 assumes fT: "finite T" and ST: "S \<subseteq> T"
1105 and z: "\<forall>i \<in> T - S. f i = 0"
1106 and fg: "\<And>x. x \<in> S \<Longrightarrow> f x = g x"
1107 shows "setsum f T = setsum g S"
1108 using setsum_mono_zero_cong_left[OF fT ST z] fg[symmetric] by auto
1111 assumes fS: "finite S"
1112 shows "setsum (\<lambda>k. if k=a then b k else 0) S = (if a \<in> S then b a else 0)"
1114 let ?f = "(\<lambda>k. if k=a then b k else 0)"
1115 {assume a: "a \<notin> S"
1116 hence "\<forall> k\<in> S. ?f k = 0" by simp
1117 hence ?thesis using a by simp}
1119 {assume a: "a \<in> S"
1122 have eq: "S = ?A \<union> ?B" using a by blast
1123 have dj: "?A \<inter> ?B = {}" by simp
1124 from fS have fAB: "finite ?A" "finite ?B" by auto
1125 have "setsum ?f S = setsum ?f ?A + setsum ?f ?B"
1126 using setsum_Un_disjoint[OF fAB dj, of ?f, unfolded eq[symmetric]]
1128 then have ?thesis using a by simp}
1129 ultimately show ?thesis by blast
1131 lemma setsum_delta':
1132 assumes fS: "finite S" shows
1133 "setsum (\<lambda>k. if a = k then b k else 0) S =
1134 (if a\<in> S then b a else 0)"
1135 using setsum_delta[OF fS, of a b, symmetric]
1136 by (auto intro: setsum_cong)
1138 lemma setsum_restrict_set:
1139 assumes fA: "finite A"
1140 shows "setsum f (A \<inter> B) = setsum (\<lambda>x. if x \<in> B then f x else 0) A"
1142 from fA have fab: "finite (A \<inter> B)" by auto
1143 have aba: "A \<inter> B \<subseteq> A" by blast
1144 let ?g = "\<lambda>x. if x \<in> A\<inter>B then f x else 0"
1145 from setsum_mono_zero_left[OF fA aba, of ?g]
1146 show ?thesis by simp
1150 assumes fA: "finite A"
1151 shows "setsum (\<lambda>x. if x \<in> B then f x else g x) A =
1152 setsum f (A \<inter> B) + setsum g (A \<inter> - B)"
1154 have a: "A = A \<inter> B \<union> A \<inter> -B" "(A \<inter> B) \<inter> (A \<inter> -B) = {}"
1157 have f: "finite (A \<inter> B)" "finite (A \<inter> -B)" by auto
1158 let ?g = "\<lambda>x. if x \<in> B then f x else g x"
1159 from setsum_Un_disjoint[OF f a(2), of ?g] a(1)
1160 show ?thesis by simp
1164 (*But we can't get rid of finite I. If infinite, although the rhs is 0,
1165 the lhs need not be, since UNION I A could still be finite.*)
1166 lemma setsum_UN_disjoint:
1167 "finite I ==> (ALL i:I. finite (A i)) ==>
1168 (ALL i:I. ALL j:I. i \<noteq> j --> A i Int A j = {}) ==>
1169 setsum f (UNION I A) = (\<Sum>i\<in>I. setsum f (A i))"
1170 by(simp add: setsum_def comm_monoid_add.fold_image_UN_disjoint cong: setsum_cong)
1172 text{*No need to assume that @{term C} is finite. If infinite, the rhs is
1173 directly 0, and @{term "Union C"} is also infinite, hence the lhs is also 0.*}
1174 lemma setsum_Union_disjoint:
1175 "[| (ALL A:C. finite A);
1176 (ALL A:C. ALL B:C. A \<noteq> B --> A Int B = {}) |]
1177 ==> setsum f (Union C) = setsum (setsum f) C"
1178 apply (cases "finite C")
1179 prefer 2 apply (force dest: finite_UnionD simp add: setsum_def)
1180 apply (frule setsum_UN_disjoint [of C id f])
1181 apply (unfold Union_def id_def, assumption+)
1184 (*But we can't get rid of finite A. If infinite, although the lhs is 0,
1185 the rhs need not be, since SIGMA A B could still be finite.*)
1186 lemma setsum_Sigma: "finite A ==> ALL x:A. finite (B x) ==>
1187 (\<Sum>x\<in>A. (\<Sum>y\<in>B x. f x y)) = (\<Sum>(x,y)\<in>(SIGMA x:A. B x). f x y)"
1188 by(simp add:setsum_def comm_monoid_add.fold_image_Sigma split_def cong:setsum_cong)
1190 text{*Here we can eliminate the finiteness assumptions, by cases.*}
1191 lemma setsum_cartesian_product:
1192 "(\<Sum>x\<in>A. (\<Sum>y\<in>B. f x y)) = (\<Sum>(x,y) \<in> A <*> B. f x y)"
1193 apply (cases "finite A")
1194 apply (cases "finite B")
1195 apply (simp add: setsum_Sigma)
1196 apply (cases "A={}", simp)
1198 apply (auto simp add: setsum_def
1199 dest: finite_cartesian_productD1 finite_cartesian_productD2)
1202 lemma setsum_addf: "setsum (%x. f x + g x) A = (setsum f A + setsum g A)"
1203 by(simp add:setsum_def comm_monoid_add.fold_image_distrib)
1206 subsubsection {* Properties in more restricted classes of structures *}
1208 lemma setsum_SucD: "setsum f A = Suc n ==> EX a:A. 0 < f a"
1209 apply (case_tac "finite A")
1210 prefer 2 apply (simp add: setsum_def)
1211 apply (erule rev_mp)
1212 apply (erule finite_induct, auto)
1215 lemma setsum_eq_0_iff [simp]:
1216 "finite F ==> (setsum f F = 0) = (ALL a:F. f a = (0::nat))"
1217 by (induct set: finite) auto
1219 lemma setsum_Un_nat: "finite A ==> finite B ==>
1220 (setsum f (A Un B) :: nat) = setsum f A + setsum f B - setsum f (A Int B)"
1221 -- {* For the natural numbers, we have subtraction. *}
1222 by (subst setsum_Un_Int [symmetric], auto simp add: algebra_simps)
1224 lemma setsum_Un: "finite A ==> finite B ==>
1225 (setsum f (A Un B) :: 'a :: ab_group_add) =
1226 setsum f A + setsum f B - setsum f (A Int B)"
1227 by (subst setsum_Un_Int [symmetric], auto simp add: algebra_simps)
1229 lemma (in comm_monoid_mult) fold_image_1: "finite S \<Longrightarrow> (\<forall>x\<in>S. f x = 1) \<Longrightarrow> fold_image op * f 1 S = 1"
1230 apply (induct set: finite)
1231 apply simp by (auto simp add: fold_image_insert)
1233 lemma (in comm_monoid_mult) fold_image_Un_one:
1234 assumes fS: "finite S" and fT: "finite T"
1235 and I0: "\<forall>x \<in> S\<inter>T. f x = 1"
1236 shows "fold_image (op *) f 1 (S \<union> T) = fold_image (op *) f 1 S * fold_image (op *) f 1 T"
1238 have "fold_image op * f 1 (S \<inter> T) = 1"
1239 apply (rule fold_image_1)
1240 using fS fT I0 by auto
1241 with fold_image_Un_Int[OF fS fT] show ?thesis by simp
1244 lemma setsum_eq_general_reverses:
1245 assumes fS: "finite S" and fT: "finite T"
1246 and kh: "\<And>y. y \<in> T \<Longrightarrow> k y \<in> S \<and> h (k y) = y"
1247 and hk: "\<And>x. x \<in> S \<Longrightarrow> h x \<in> T \<and> k (h x) = x \<and> g (h x) = f x"
1248 shows "setsum f S = setsum g T"
1249 apply (simp add: setsum_def fS fT)
1250 apply (rule comm_monoid_add.fold_image_eq_general_inverses[OF fS])
1257 lemma setsum_Un_zero:
1258 assumes fS: "finite S" and fT: "finite T"
1259 and I0: "\<forall>x \<in> S\<inter>T. f x = 0"
1260 shows "setsum f (S \<union> T) = setsum f S + setsum f T"
1262 apply (simp add: setsum_def)
1263 apply (rule comm_monoid_add.fold_image_Un_one)
1267 lemma setsum_UNION_zero:
1268 assumes fS: "finite S" and fSS: "\<forall>T \<in> S. finite T"
1269 and f0: "\<And>T1 T2 x. T1\<in>S \<Longrightarrow> T2\<in>S \<Longrightarrow> T1 \<noteq> T2 \<Longrightarrow> x \<in> T1 \<Longrightarrow> x \<in> T2 \<Longrightarrow> f x = 0"
1270 shows "setsum f (\<Union>S) = setsum (\<lambda>T. setsum f T) S"
1272 proof(induct rule: finite_induct[OF fS])
1273 case 1 thus ?case by simp
1276 then have fTF: "finite T" "\<forall>T\<in>F. finite T" "finite F" and TF: "T \<notin> F"
1277 and H: "setsum f (\<Union> F) = setsum (setsum f) F" by (auto simp add: finite_insert)
1278 from fTF have fUF: "finite (\<Union>F)" by (auto intro: finite_Union)
1279 from "2.prems" TF fTF
1281 by (auto simp add: H[symmetric] intro: setsum_Un_zero[OF fTF(1) fUF, of f])
1285 lemma setsum_diff1_nat: "(setsum f (A - {a}) :: nat) =
1286 (if a:A then setsum f A - f a else setsum f A)"
1287 apply (case_tac "finite A")
1288 prefer 2 apply (simp add: setsum_def)
1289 apply (erule finite_induct)
1290 apply (auto simp add: insert_Diff_if)
1291 apply (drule_tac a = a in mk_disjoint_insert, auto)
1294 lemma setsum_diff1: "finite A \<Longrightarrow>
1295 (setsum f (A - {a}) :: ('a::ab_group_add)) =
1296 (if a:A then setsum f A - f a else setsum f A)"
1297 by (erule finite_induct) (auto simp add: insert_Diff_if)
1299 lemma setsum_diff1'[rule_format]:
1300 "finite A \<Longrightarrow> a \<in> A \<longrightarrow> (\<Sum> x \<in> A. f x) = f a + (\<Sum> x \<in> (A - {a}). f x)"
1301 apply (erule finite_induct[where F=A and P="% A. (a \<in> A \<longrightarrow> (\<Sum> x \<in> A. f x) = f a + (\<Sum> x \<in> (A - {a}). f x))"])
1302 apply (auto simp add: insert_Diff_if add_ac)
1305 (* By Jeremy Siek: *)
1307 lemma setsum_diff_nat:
1308 assumes "finite B" and "B \<subseteq> A"
1309 shows "(setsum f (A - B) :: nat) = (setsum f A) - (setsum f B)"
1312 show "setsum f (A - {}) = (setsum f A) - (setsum f {})" by simp
1314 fix F x assume finF: "finite F" and xnotinF: "x \<notin> F"
1315 and xFinA: "insert x F \<subseteq> A"
1316 and IH: "F \<subseteq> A \<Longrightarrow> setsum f (A - F) = setsum f A - setsum f F"
1317 from xnotinF xFinA have xinAF: "x \<in> (A - F)" by simp
1318 from xinAF have A: "setsum f ((A - F) - {x}) = setsum f (A - F) - f x"
1319 by (simp add: setsum_diff1_nat)
1320 from xFinA have "F \<subseteq> A" by simp
1321 with IH have "setsum f (A - F) = setsum f A - setsum f F" by simp
1322 with A have B: "setsum f ((A - F) - {x}) = setsum f A - setsum f F - f x"
1324 from xnotinF have "A - insert x F = (A - F) - {x}" by auto
1325 with B have C: "setsum f (A - insert x F) = setsum f A - setsum f F - f x"
1327 from finF xnotinF have "setsum f (insert x F) = setsum f F + f x" by simp
1328 with C have "setsum f (A - insert x F) = setsum f A - setsum f (insert x F)"
1330 thus "setsum f (A - insert x F) = setsum f A - setsum f (insert x F)" by simp
1334 assumes le: "finite A" "B \<subseteq> A"
1335 shows "setsum f (A - B) = setsum f A - ((setsum f B)::('a::ab_group_add))"
1337 from le have finiteB: "finite B" using finite_subset by auto
1338 show ?thesis using finiteB le
1344 thus ?case using le finiteB
1345 by (simp add: Diff_insert[where a=x and B=F] setsum_diff1 insert_absorb)
1350 assumes le: "\<And>i. i\<in>K \<Longrightarrow> f (i::'a) \<le> ((g i)::('b::{comm_monoid_add, pordered_ab_semigroup_add}))"
1351 shows "(\<Sum>i\<in>K. f i) \<le> (\<Sum>i\<in>K. g i)"
1352 proof (cases "finite K")
1354 thus ?thesis using le
1360 thus ?case using add_mono by fastsimp
1365 by (simp add: setsum_def)
1368 lemma setsum_strict_mono:
1369 fixes f :: "'a \<Rightarrow> 'b::{pordered_cancel_ab_semigroup_add,comm_monoid_add}"
1370 assumes "finite A" "A \<noteq> {}"
1371 and "!!x. x:A \<Longrightarrow> f x < g x"
1372 shows "setsum f A < setsum g A"
1374 proof (induct rule: finite_ne_induct)
1375 case singleton thus ?case by simp
1377 case insert thus ?case by (auto simp: add_strict_mono)
1381 "setsum (%x. - (f x)::'a::ab_group_add) A = - setsum f A"
1382 proof (cases "finite A")
1383 case True thus ?thesis by (induct set: finite) auto
1385 case False thus ?thesis by (simp add: setsum_def)
1388 lemma setsum_subtractf:
1389 "setsum (%x. ((f x)::'a::ab_group_add) - g x) A =
1390 setsum f A - setsum g A"
1391 proof (cases "finite A")
1392 case True thus ?thesis by (simp add: diff_minus setsum_addf setsum_negf)
1394 case False thus ?thesis by (simp add: setsum_def)
1397 lemma setsum_nonneg:
1398 assumes nn: "\<forall>x\<in>A. (0::'a::{pordered_ab_semigroup_add,comm_monoid_add}) \<le> f x"
1399 shows "0 \<le> setsum f A"
1400 proof (cases "finite A")
1401 case True thus ?thesis using nn
1403 case empty then show ?case by simp
1406 then have "0 + 0 \<le> f x + setsum f F" by (blast intro: add_mono)
1407 with insert show ?case by simp
1410 case False thus ?thesis by (simp add: setsum_def)
1413 lemma setsum_nonpos:
1414 assumes np: "\<forall>x\<in>A. f x \<le> (0::'a::{pordered_ab_semigroup_add,comm_monoid_add})"
1415 shows "setsum f A \<le> 0"
1416 proof (cases "finite A")
1417 case True thus ?thesis using np
1419 case empty then show ?case by simp
1422 then have "f x + setsum f F \<le> 0 + 0" by (blast intro: add_mono)
1423 with insert show ?case by simp
1426 case False thus ?thesis by (simp add: setsum_def)
1430 fixes f :: "'a \<Rightarrow> 'b :: {pordered_ab_semigroup_add_imp_le,comm_monoid_add}"
1431 assumes fin: "finite B" and sub: "A \<subseteq> B" and nn: "\<And>b. b \<in> B-A \<Longrightarrow> 0 \<le> f b"
1432 shows "setsum f A \<le> setsum f B"
1434 have "setsum f A \<le> setsum f A + setsum f (B-A)"
1435 by(simp add: add_increasing2[OF setsum_nonneg] nn Ball_def)
1436 also have "\<dots> = setsum f (A \<union> (B-A))" using fin finite_subset[OF sub fin]
1437 by (simp add:setsum_Un_disjoint del:Un_Diff_cancel)
1438 also have "A \<union> (B-A) = B" using sub by blast
1439 finally show ?thesis .
1442 lemma setsum_mono3: "finite B ==> A <= B ==>
1444 0 <= ((f x)::'a::{comm_monoid_add,pordered_ab_semigroup_add}) ==>
1445 setsum f A <= setsum f B"
1446 apply (subgoal_tac "setsum f B = setsum f A + setsum f (B - A)")
1447 apply (erule ssubst)
1448 apply (subgoal_tac "setsum f A + 0 <= setsum f A + setsum f (B - A)")
1450 apply (rule add_left_mono)
1451 apply (erule setsum_nonneg)
1452 apply (subst setsum_Un_disjoint [THEN sym])
1453 apply (erule finite_subset, assumption)
1454 apply (rule finite_subset)
1458 apply (rule setsum_cong)
1462 lemma setsum_right_distrib:
1463 fixes f :: "'a => ('b::semiring_0)"
1464 shows "r * setsum f A = setsum (%n. r * f n) A"
1465 proof (cases "finite A")
1469 case empty thus ?case by simp
1471 case (insert x A) thus ?case by (simp add: right_distrib)
1474 case False thus ?thesis by (simp add: setsum_def)
1477 lemma setsum_left_distrib:
1478 "setsum f A * (r::'a::semiring_0) = (\<Sum>n\<in>A. f n * r)"
1479 proof (cases "finite A")
1483 case empty thus ?case by simp
1485 case (insert x A) thus ?case by (simp add: left_distrib)
1488 case False thus ?thesis by (simp add: setsum_def)
1491 lemma setsum_divide_distrib:
1492 "setsum f A / (r::'a::field) = (\<Sum>n\<in>A. f n / r)"
1493 proof (cases "finite A")
1497 case empty thus ?case by simp
1499 case (insert x A) thus ?case by (simp add: add_divide_distrib)
1502 case False thus ?thesis by (simp add: setsum_def)
1505 lemma setsum_abs[iff]:
1506 fixes f :: "'a => ('b::pordered_ab_group_add_abs)"
1507 shows "abs (setsum f A) \<le> setsum (%i. abs(f i)) A"
1508 proof (cases "finite A")
1512 case empty thus ?case by simp
1515 thus ?case by (auto intro: abs_triangle_ineq order_trans)
1518 case False thus ?thesis by (simp add: setsum_def)
1521 lemma setsum_abs_ge_zero[iff]:
1522 fixes f :: "'a => ('b::pordered_ab_group_add_abs)"
1523 shows "0 \<le> setsum (%i. abs(f i)) A"
1524 proof (cases "finite A")
1528 case empty thus ?case by simp
1530 case (insert x A) thus ?case by (auto simp: add_nonneg_nonneg)
1533 case False thus ?thesis by (simp add: setsum_def)
1536 lemma abs_setsum_abs[simp]:
1537 fixes f :: "'a => ('b::pordered_ab_group_add_abs)"
1538 shows "abs (\<Sum>a\<in>A. abs(f a)) = (\<Sum>a\<in>A. abs(f a))"
1539 proof (cases "finite A")
1543 case empty thus ?case by simp
1546 hence "\<bar>\<Sum>a\<in>insert a A. \<bar>f a\<bar>\<bar> = \<bar>\<bar>f a\<bar> + (\<Sum>a\<in>A. \<bar>f a\<bar>)\<bar>" by simp
1547 also have "\<dots> = \<bar>\<bar>f a\<bar> + \<bar>\<Sum>a\<in>A. \<bar>f a\<bar>\<bar>\<bar>" using insert by simp
1548 also have "\<dots> = \<bar>f a\<bar> + \<bar>\<Sum>a\<in>A. \<bar>f a\<bar>\<bar>"
1549 by (simp del: abs_of_nonneg)
1550 also have "\<dots> = (\<Sum>a\<in>insert a A. \<bar>f a\<bar>)" using insert by simp
1551 finally show ?case .
1554 case False thus ?thesis by (simp add: setsum_def)
1558 text {* Commuting outer and inner summation *}
1561 "inj_on (%(i, j). (j, i)) (A \<times> B)"
1562 by (unfold inj_on_def) fast
1565 "(%(i, j). (j, i)) ` (A \<times> B) = B \<times> A"
1566 by (simp add: split_def image_def) blast
1568 lemma setsum_commute:
1569 "(\<Sum>i\<in>A. \<Sum>j\<in>B. f i j) = (\<Sum>j\<in>B. \<Sum>i\<in>A. f i j)"
1570 proof (simp add: setsum_cartesian_product)
1571 have "(\<Sum>(x,y) \<in> A <*> B. f x y) =
1572 (\<Sum>(y,x) \<in> (%(i, j). (j, i)) ` (A \<times> B). f x y)"
1574 apply (simp add: setsum_reindex [where f = "%(i, j). (j, i)"] swap_inj_on)
1575 apply (simp add: split_def)
1577 also have "... = (\<Sum>(y,x)\<in>B \<times> A. f x y)"
1579 apply (simp add: swap_product)
1581 finally show "?s = ?t" .
1584 lemma setsum_product:
1585 fixes f :: "'a => ('b::semiring_0)"
1586 shows "setsum f A * setsum g B = (\<Sum>i\<in>A. \<Sum>j\<in>B. f i * g j)"
1587 by (simp add: setsum_right_distrib setsum_left_distrib) (rule setsum_commute)
1590 subsection {* Generalized product over a set *}
1592 definition setprod :: "('a => 'b) => 'a set => 'b::comm_monoid_mult"
1593 where "setprod f A == if finite A then fold_image (op *) f 1 A else 1"
1596 Setprod ("\<Prod>_" [1000] 999) where
1597 "\<Prod>A == setprod (%x. x) A"
1600 "_setprod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(3PROD _:_. _)" [0, 51, 10] 10)
1602 "_setprod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(3\<Prod>_\<in>_. _)" [0, 51, 10] 10)
1603 syntax (HTML output)
1604 "_setprod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(3\<Prod>_\<in>_. _)" [0, 51, 10] 10)
1606 translations -- {* Beware of argument permutation! *}
1607 "PROD i:A. b" == "CONST setprod (%i. b) A"
1608 "\<Prod>i\<in>A. b" == "CONST setprod (%i. b) A"
1610 text{* Instead of @{term"\<Prod>x\<in>{x. P}. e"} we introduce the shorter
1611 @{text"\<Prod>x|P. e"}. *}
1614 "_qsetprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3PROD _ |/ _./ _)" [0,0,10] 10)
1616 "_qsetprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3\<Prod>_ | (_)./ _)" [0,0,10] 10)
1617 syntax (HTML output)
1618 "_qsetprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3\<Prod>_ | (_)./ _)" [0,0,10] 10)
1621 "PROD x|P. t" => "CONST setprod (%x. t) {x. P}"
1622 "\<Prod>x|P. t" => "CONST setprod (%x. t) {x. P}"
1625 lemma setprod_empty [simp]: "setprod f {} = 1"
1626 by (auto simp add: setprod_def)
1628 lemma setprod_insert [simp]: "[| finite A; a \<notin> A |] ==>
1629 setprod f (insert a A) = f a * setprod f A"
1630 by (simp add: setprod_def)
1632 lemma setprod_infinite [simp]: "~ finite A ==> setprod f A = 1"
1633 by (simp add: setprod_def)
1635 lemma setprod_reindex:
1636 "inj_on f B ==> setprod h (f ` B) = setprod (h \<circ> f) B"
1637 by(auto simp: setprod_def fold_image_reindex dest!:finite_imageD)
1639 lemma setprod_reindex_id: "inj_on f B ==> setprod f B = setprod id (f ` B)"
1640 by (auto simp add: setprod_reindex)
1643 "A = B ==> (!!x. x:B ==> f x = g x) ==> setprod f A = setprod g B"
1644 by(fastsimp simp: setprod_def intro: fold_image_cong)
1646 lemma strong_setprod_cong[cong]:
1647 "A = B ==> (!!x. x:B =simp=> f x = g x) ==> setprod f A = setprod g B"
1648 by(fastsimp simp: simp_implies_def setprod_def intro: fold_image_cong)
1650 lemma setprod_reindex_cong: "inj_on f A ==>
1651 B = f ` A ==> g = h \<circ> f ==> setprod h B = setprod g A"
1652 by (frule setprod_reindex, simp)
1654 lemma strong_setprod_reindex_cong: assumes i: "inj_on f A"
1655 and B: "B = f ` A" and eq: "\<And>x. x \<in> A \<Longrightarrow> g x = (h \<circ> f) x"
1656 shows "setprod h B = setprod g A"
1658 have "setprod h B = setprod (h o f) A"
1659 by (simp add: B setprod_reindex[OF i, of h])
1660 then show ?thesis apply simp
1661 apply (rule setprod_cong)
1666 lemma setprod_Un_one:
1667 assumes fS: "finite S" and fT: "finite T"
1668 and I0: "\<forall>x \<in> S\<inter>T. f x = 1"
1669 shows "setprod f (S \<union> T) = setprod f S * setprod f T"
1671 apply (simp add: setprod_def)
1672 apply (rule fold_image_Un_one)
1676 lemma setprod_1: "setprod (%i. 1) A = 1"
1677 apply (case_tac "finite A")
1678 apply (erule finite_induct, auto simp add: mult_ac)
1681 lemma setprod_1': "ALL a:F. f a = 1 ==> setprod f F = 1"
1682 apply (subgoal_tac "setprod f F = setprod (%x. 1) F")
1683 apply (erule ssubst, rule setprod_1)
1684 apply (rule setprod_cong, auto)
1687 lemma setprod_Un_Int: "finite A ==> finite B
1688 ==> setprod g (A Un B) * setprod g (A Int B) = setprod g A * setprod g B"
1689 by(simp add: setprod_def fold_image_Un_Int[symmetric])
1691 lemma setprod_Un_disjoint: "finite A ==> finite B
1692 ==> A Int B = {} ==> setprod g (A Un B) = setprod g A * setprod g B"
1693 by (subst setprod_Un_Int [symmetric], auto)
1695 lemma setprod_mono_one_left:
1696 assumes fT: "finite T" and ST: "S \<subseteq> T"
1697 and z: "\<forall>i \<in> T - S. f i = 1"
1698 shows "setprod f S = setprod f T"
1700 have eq: "T = S \<union> (T - S)" using ST by blast
1701 have d: "S \<inter> (T - S) = {}" using ST by blast
1702 from fT ST have f: "finite S" "finite (T - S)" by (auto intro: finite_subset)
1704 by (simp add: setprod_Un_disjoint[OF f d, unfolded eq[symmetric]] setprod_1'[OF z])
1707 lemmas setprod_mono_one_right = setprod_mono_one_left [THEN sym]
1709 lemma setprod_delta:
1710 assumes fS: "finite S"
1711 shows "setprod (\<lambda>k. if k=a then b k else 1) S = (if a \<in> S then b a else 1)"
1713 let ?f = "(\<lambda>k. if k=a then b k else 1)"
1714 {assume a: "a \<notin> S"
1715 hence "\<forall> k\<in> S. ?f k = 1" by simp
1716 hence ?thesis using a by (simp add: setprod_1 cong add: setprod_cong) }
1718 {assume a: "a \<in> S"
1721 have eq: "S = ?A \<union> ?B" using a by blast
1722 have dj: "?A \<inter> ?B = {}" by simp
1723 from fS have fAB: "finite ?A" "finite ?B" by auto
1724 have fA1: "setprod ?f ?A = 1" apply (rule setprod_1') by auto
1725 have "setprod ?f ?A * setprod ?f ?B = setprod ?f S"
1726 using setprod_Un_disjoint[OF fAB dj, of ?f, unfolded eq[symmetric]]
1728 then have ?thesis using a by (simp add: fA1 cong add: setprod_cong cong del: if_weak_cong)}
1729 ultimately show ?thesis by blast
1732 lemma setprod_delta':
1733 assumes fS: "finite S" shows
1734 "setprod (\<lambda>k. if a = k then b k else 1) S =
1735 (if a\<in> S then b a else 1)"
1736 using setprod_delta[OF fS, of a b, symmetric]
1737 by (auto intro: setprod_cong)
1740 lemma setprod_UN_disjoint:
1741 "finite I ==> (ALL i:I. finite (A i)) ==>
1742 (ALL i:I. ALL j:I. i \<noteq> j --> A i Int A j = {}) ==>
1743 setprod f (UNION I A) = setprod (%i. setprod f (A i)) I"
1744 by(simp add: setprod_def fold_image_UN_disjoint cong: setprod_cong)
1746 lemma setprod_Union_disjoint:
1747 "[| (ALL A:C. finite A);
1748 (ALL A:C. ALL B:C. A \<noteq> B --> A Int B = {}) |]
1749 ==> setprod f (Union C) = setprod (setprod f) C"
1750 apply (cases "finite C")
1751 prefer 2 apply (force dest: finite_UnionD simp add: setprod_def)
1752 apply (frule setprod_UN_disjoint [of C id f])
1753 apply (unfold Union_def id_def, assumption+)
1756 lemma setprod_Sigma: "finite A ==> ALL x:A. finite (B x) ==>
1757 (\<Prod>x\<in>A. (\<Prod>y\<in> B x. f x y)) =
1758 (\<Prod>(x,y)\<in>(SIGMA x:A. B x). f x y)"
1759 by(simp add:setprod_def fold_image_Sigma split_def cong:setprod_cong)
1761 text{*Here we can eliminate the finiteness assumptions, by cases.*}
1762 lemma setprod_cartesian_product:
1763 "(\<Prod>x\<in>A. (\<Prod>y\<in> B. f x y)) = (\<Prod>(x,y)\<in>(A <*> B). f x y)"
1764 apply (cases "finite A")
1765 apply (cases "finite B")
1766 apply (simp add: setprod_Sigma)
1767 apply (cases "A={}", simp)
1768 apply (simp add: setprod_1)
1769 apply (auto simp add: setprod_def
1770 dest: finite_cartesian_productD1 finite_cartesian_productD2)
1773 lemma setprod_timesf:
1774 "setprod (%x. f x * g x) A = (setprod f A * setprod g A)"
1775 by(simp add:setprod_def fold_image_distrib)
1778 subsubsection {* Properties in more restricted classes of structures *}
1780 lemma setprod_eq_1_iff [simp]:
1781 "finite F ==> (setprod f F = 1) = (ALL a:F. f a = (1::nat))"
1782 by (induct set: finite) auto
1785 "finite A ==> EX x: A. f x = (0::'a::comm_semiring_1) ==> setprod f A = 0"
1786 apply (induct set: finite, force, clarsimp)
1787 apply (erule disjE, auto)
1790 lemma setprod_nonneg [rule_format]:
1791 "(ALL x: A. (0::'a::ordered_semidom) \<le> f x) --> 0 \<le> setprod f A"
1792 by (cases "finite A", induct set: finite, simp_all add: mult_nonneg_nonneg)
1794 lemma setprod_pos [rule_format]: "(ALL x: A. (0::'a::ordered_semidom) < f x)
1795 --> 0 < setprod f A"
1796 by (cases "finite A", induct set: finite, simp_all add: mult_pos_pos)
1798 lemma setprod_nonzero [rule_format]:
1799 "(ALL x y. (x::'a::comm_semiring_1) * y = 0 --> x = 0 | y = 0) ==>
1800 finite A ==> (ALL x: A. f x \<noteq> (0::'a)) --> setprod f A \<noteq> 0"
1801 by (erule finite_induct, auto)
1803 lemma setprod_zero_eq:
1804 "(ALL x y. (x::'a::comm_semiring_1) * y = 0 --> x = 0 | y = 0) ==>
1805 finite A ==> (setprod f A = (0::'a)) = (EX x: A. f x = 0)"
1806 by (insert setprod_zero [of A f] setprod_nonzero [of A f], blast)
1808 lemma setprod_nonzero_field:
1809 "finite A ==> (ALL x: A. f x \<noteq> (0::'a::idom)) ==> setprod f A \<noteq> 0"
1810 by (rule setprod_nonzero, auto)
1812 lemma setprod_zero_eq_field:
1813 "finite A ==> (setprod f A = (0::'a::idom)) = (EX x: A. f x = 0)"
1814 by (rule setprod_zero_eq, auto)
1816 lemma setprod_Un: "finite A ==> finite B ==> (ALL x: A Int B. f x \<noteq> 0) ==>
1817 (setprod f (A Un B) :: 'a ::{field})
1818 = setprod f A * setprod f B / setprod f (A Int B)"
1819 apply (subst setprod_Un_Int [symmetric], auto)
1820 apply (subgoal_tac "finite (A Int B)")
1821 apply (frule setprod_nonzero_field [of "A Int B" f], assumption)
1822 apply (subst times_divide_eq_right [THEN sym], auto)
1825 lemma setprod_diff1: "finite A ==> f a \<noteq> 0 ==>
1826 (setprod f (A - {a}) :: 'a :: {field}) =
1827 (if a:A then setprod f A / f a else setprod f A)"
1828 by (erule finite_induct) (auto simp add: insert_Diff_if)
1830 lemma setprod_inversef: "finite A ==>
1831 ALL x: A. f x \<noteq> (0::'a::{field,division_by_zero}) ==>
1832 setprod (inverse \<circ> f) A = inverse (setprod f A)"
1833 by (erule finite_induct) auto
1835 lemma setprod_dividef:
1837 \<forall>x \<in> A. g x \<noteq> (0::'a::{field,division_by_zero})|]
1838 ==> setprod (%x. f x / g x) A = setprod f A / setprod g A"
1840 "setprod (%x. f x / g x) A = setprod (%x. f x * (inverse \<circ> g) x) A")
1841 apply (erule ssubst)
1842 apply (subst divide_inverse)
1843 apply (subst setprod_timesf)
1844 apply (subst setprod_inversef, assumption+, rule refl)
1845 apply (rule setprod_cong, rule refl)
1846 apply (subst divide_inverse, auto)
1849 lemma setprod_dvd_setprod [rule_format]:
1850 "(ALL x : A. f x dvd g x) \<longrightarrow> setprod f A dvd setprod g A"
1851 apply (cases "finite A")
1852 apply (induct set: finite)
1853 apply (auto simp add: dvd_def)
1854 apply (rule_tac x = "k * ka" in exI)
1855 apply (simp add: algebra_simps)
1858 lemma setprod_dvd_setprod_subset:
1859 "finite B \<Longrightarrow> A <= B \<Longrightarrow> setprod f A dvd setprod f B"
1860 apply (subgoal_tac "setprod f B = setprod f A * setprod f (B - A)")
1861 apply (unfold dvd_def, blast)
1862 apply (subst setprod_Un_disjoint [symmetric])
1863 apply (auto elim: finite_subset intro: setprod_cong)
1866 lemma setprod_dvd_setprod_subset2:
1867 "finite B \<Longrightarrow> A <= B \<Longrightarrow> ALL x : A. (f x::'a::comm_semiring_1) dvd g x \<Longrightarrow>
1868 setprod f A dvd setprod g B"
1869 apply (rule dvd_trans)
1870 apply (rule setprod_dvd_setprod, erule (1) bspec)
1871 apply (erule (1) setprod_dvd_setprod_subset)
1874 lemma dvd_setprod: "finite A \<Longrightarrow> i:A \<Longrightarrow>
1875 (f i ::'a::comm_semiring_1) dvd setprod f A"
1876 by (induct set: finite) (auto intro: dvd_mult)
1878 lemma dvd_setsum [rule_format]: "(ALL i : A. d dvd f i) \<longrightarrow>
1879 (d::'a::comm_semiring_1) dvd (SUM x : A. f x)"
1880 apply (cases "finite A")
1881 apply (induct set: finite)
1886 subsection {* Finite cardinality *}
1888 text {* This definition, although traditional, is ugly to work with:
1889 @{text "card A == LEAST n. EX f. A = {f i | i. i < n}"}.
1890 But now that we have @{text setsum} things are easy:
1893 definition card :: "'a set \<Rightarrow> nat"
1894 where "card A = setsum (\<lambda>x. 1) A"
1896 lemma card_empty [simp]: "card {} = 0"
1897 by (simp add: card_def)
1899 lemma card_infinite [simp]: "~ finite A ==> card A = 0"
1900 by (simp add: card_def)
1902 lemma card_eq_setsum: "card A = setsum (%x. 1) A"
1903 by (simp add: card_def)
1905 lemma card_insert_disjoint [simp]:
1906 "finite A ==> x \<notin> A ==> card (insert x A) = Suc(card A)"
1907 by(simp add: card_def)
1909 lemma card_insert_if:
1910 "finite A ==> card (insert x A) = (if x:A then card A else Suc(card(A)))"
1911 by (simp add: insert_absorb)
1913 lemma card_0_eq [simp,noatp]: "finite A ==> (card A = 0) = (A = {})"
1915 apply (drule_tac a = x in mk_disjoint_insert, clarify, auto)
1918 lemma card_eq_0_iff: "(card A = 0) = (A = {} | ~ finite A)"
1922 lemma card_Suc_Diff1: "finite A ==> x: A ==> Suc (card (A - {x})) = card A"
1923 apply(rule_tac t = A in insert_Diff [THEN subst], assumption)
1924 apply(simp del:insert_Diff_single)
1927 lemma card_Diff_singleton:
1928 "finite A ==> x: A ==> card (A - {x}) = card A - 1"
1929 by (simp add: card_Suc_Diff1 [symmetric])
1931 lemma card_Diff_singleton_if:
1932 "finite A ==> card (A-{x}) = (if x : A then card A - 1 else card A)"
1933 by (simp add: card_Diff_singleton)
1935 lemma card_Diff_insert[simp]:
1936 assumes "finite A" and "a:A" and "a ~: B"
1937 shows "card(A - insert a B) = card(A - B) - 1"
1939 have "A - insert a B = (A - B) - {a}" using assms by blast
1940 then show ?thesis using assms by(simp add:card_Diff_singleton)
1943 lemma card_insert: "finite A ==> card (insert x A) = Suc (card (A - {x}))"
1944 by (simp add: card_insert_if card_Suc_Diff1 del:card_Diff_insert)
1946 lemma card_insert_le: "finite A ==> card A <= card (insert x A)"
1947 by (simp add: card_insert_if)
1949 lemma card_mono: "\<lbrakk> finite B; A \<subseteq> B \<rbrakk> \<Longrightarrow> card A \<le> card B"
1950 by (simp add: card_def setsum_mono2)
1952 lemma card_seteq: "finite B ==> (!!A. A <= B ==> card B <= card A ==> A = B)"
1953 apply (induct set: finite, simp, clarify)
1954 apply (subgoal_tac "finite A & A - {x} <= F")
1955 prefer 2 apply (blast intro: finite_subset, atomize)
1956 apply (drule_tac x = "A - {x}" in spec)
1957 apply (simp add: card_Diff_singleton_if split add: split_if_asm)
1958 apply (case_tac "card A", auto)
1961 lemma psubset_card_mono: "finite B ==> A < B ==> card A < card B"
1962 apply (simp add: psubset_eq linorder_not_le [symmetric])
1963 apply (blast dest: card_seteq)
1966 lemma card_Un_Int: "finite A ==> finite B
1967 ==> card A + card B = card (A Un B) + card (A Int B)"
1968 by(simp add:card_def setsum_Un_Int)
1970 lemma card_Un_disjoint: "finite A ==> finite B
1971 ==> A Int B = {} ==> card (A Un B) = card A + card B"
1972 by (simp add: card_Un_Int)
1974 lemma card_Diff_subset:
1975 "finite B ==> B <= A ==> card (A - B) = card A - card B"
1976 by(simp add:card_def setsum_diff_nat)
1978 lemma card_Diff1_less: "finite A ==> x: A ==> card (A - {x}) < card A"
1979 apply (rule Suc_less_SucD)
1980 apply (simp add: card_Suc_Diff1 del:card_Diff_insert)
1983 lemma card_Diff2_less:
1984 "finite A ==> x: A ==> y: A ==> card (A - {x} - {y}) < card A"
1985 apply (case_tac "x = y")
1986 apply (simp add: card_Diff1_less del:card_Diff_insert)
1987 apply (rule less_trans)
1988 prefer 2 apply (auto intro!: card_Diff1_less simp del:card_Diff_insert)
1991 lemma card_Diff1_le: "finite A ==> card (A - {x}) <= card A"
1992 apply (case_tac "x : A")
1993 apply (simp_all add: card_Diff1_less less_imp_le)
1996 lemma card_psubset: "finite B ==> A \<subseteq> B ==> card A < card B ==> A < B"
1997 by (erule psubsetI, blast)
1999 lemma insert_partition:
2000 "\<lbrakk> x \<notin> F; \<forall>c1 \<in> insert x F. \<forall>c2 \<in> insert x F. c1 \<noteq> c2 \<longrightarrow> c1 \<inter> c2 = {} \<rbrakk>
2001 \<Longrightarrow> x \<inter> \<Union> F = {}"
2004 text{* main cardinality theorem *}
2005 lemma card_partition [rule_format]:
2007 finite (\<Union> C) -->
2008 (\<forall>c\<in>C. card c = k) -->
2009 (\<forall>c1 \<in> C. \<forall>c2 \<in> C. c1 \<noteq> c2 --> c1 \<inter> c2 = {}) -->
2010 k * card(C) = card (\<Union> C)"
2011 apply (erule finite_induct, simp)
2012 apply (simp add: card_insert_disjoint card_Un_disjoint insert_partition
2013 finite_subset [of _ "\<Union> (insert x F)"])
2017 text{*The form of a finite set of given cardinality*}
2020 assumes "card A = Suc k"
2021 shows "\<exists>b B. A = insert b B & b \<notin> B & card B = k & (k=0 \<longrightarrow> B={})"
2023 have fin: "finite A" using assms by (auto intro: ccontr)
2024 moreover have "card A \<noteq> 0" using assms by auto
2025 ultimately obtain b where b: "b \<in> A" by auto
2027 proof (intro exI conjI)
2028 show "A = insert b (A-{b})" using b by blast
2029 show "b \<notin> A - {b}" by blast
2030 show "card (A - {b}) = k" and "k = 0 \<longrightarrow> A - {b} = {}"
2031 using assms b fin by(fastsimp dest:mk_disjoint_insert)+
2037 (\<exists>b B. A = insert b B & b \<notin> B & card B = k & (k=0 \<longrightarrow> B={}))"
2039 apply(erule card_eq_SucD)
2041 apply(subst card_insert)
2042 apply(auto intro:ccontr)
2045 lemma setsum_constant [simp]: "(\<Sum>x \<in> A. y) = of_nat(card A) * y"
2046 apply (cases "finite A")
2047 apply (erule finite_induct)
2048 apply (auto simp add: algebra_simps)
2051 lemma setprod_constant: "finite A ==> (\<Prod>x\<in> A. (y::'a::{recpower, comm_monoid_mult})) = y^(card A)"
2052 apply (erule finite_induct)
2053 apply (auto simp add: power_Suc)
2056 lemma setprod_gen_delta:
2057 assumes fS: "finite S"
2058 shows "setprod (\<lambda>k. if k=a then b k else c) S = (if a \<in> S then (b a ::'a::{comm_monoid_mult, recpower}) * c^ (card S - 1) else c^ card S)"
2060 let ?f = "(\<lambda>k. if k=a then b k else c)"
2061 {assume a: "a \<notin> S"
2062 hence "\<forall> k\<in> S. ?f k = c" by simp
2063 hence ?thesis using a setprod_constant[OF fS, of c] by (simp add: setprod_1 cong add: setprod_cong) }
2065 {assume a: "a \<in> S"
2068 have eq: "S = ?A \<union> ?B" using a by blast
2069 have dj: "?A \<inter> ?B = {}" by simp
2070 from fS have fAB: "finite ?A" "finite ?B" by auto
2071 have fA0:"setprod ?f ?A = setprod (\<lambda>i. c) ?A"
2072 apply (rule setprod_cong) by auto
2073 have cA: "card ?A = card S - 1" using fS a by auto
2074 have fA1: "setprod ?f ?A = c ^ card ?A" unfolding fA0 apply (rule setprod_constant) using fS by auto
2075 have "setprod ?f ?A * setprod ?f ?B = setprod ?f S"
2076 using setprod_Un_disjoint[OF fAB dj, of ?f, unfolded eq[symmetric]]
2078 then have ?thesis using a cA
2079 by (simp add: fA1 ring_simps cong add: setprod_cong cong del: if_weak_cong)}
2080 ultimately show ?thesis by blast
2084 lemma setsum_bounded:
2085 assumes le: "\<And>i. i\<in>A \<Longrightarrow> f i \<le> (K::'a::{semiring_1, pordered_ab_semigroup_add})"
2086 shows "setsum f A \<le> of_nat(card A) * K"
2087 proof (cases "finite A")
2089 thus ?thesis using le setsum_mono[where K=A and g = "%x. K"] by simp
2091 case False thus ?thesis by (simp add: setsum_def)
2095 subsubsection {* Cardinality of unions *}
2097 lemma card_UN_disjoint:
2098 "finite I ==> (ALL i:I. finite (A i)) ==>
2099 (ALL i:I. ALL j:I. i \<noteq> j --> A i Int A j = {})
2100 ==> card (UNION I A) = (\<Sum>i\<in>I. card(A i))"
2101 apply (simp add: card_def del: setsum_constant)
2103 "setsum (%i. card (A i)) I = setsum (%i. (setsum (%x. 1) (A i))) I")
2104 apply (simp add: setsum_UN_disjoint del: setsum_constant)
2105 apply (simp cong: setsum_cong)
2108 lemma card_Union_disjoint:
2109 "finite C ==> (ALL A:C. finite A) ==>
2110 (ALL A:C. ALL B:C. A \<noteq> B --> A Int B = {})
2111 ==> card (Union C) = setsum card C"
2112 apply (frule card_UN_disjoint [of C id])
2113 apply (unfold Union_def id_def, assumption+)
2117 subsubsection {* Cardinality of image *}
2119 text{*The image of a finite set can be expressed using @{term fold_image}.*}
2120 lemma image_eq_fold_image:
2121 "finite A ==> f ` A = fold_image (op Un) (%x. {f x}) {} A"
2122 proof (induct rule: finite_induct)
2123 case empty then show ?case by simp
2125 interpret ab_semigroup_mult "op Un"
2128 then show ?case by simp
2131 lemma card_image_le: "finite A ==> card (f ` A) <= card A"
2132 apply (induct set: finite)
2134 apply (simp add: le_SucI finite_imageI card_insert_if)
2137 lemma card_image: "inj_on f A ==> card (f ` A) = card A"
2138 by(simp add:card_def setsum_reindex o_def del:setsum_constant)
2140 lemma endo_inj_surj: "finite A ==> f ` A \<subseteq> A ==> inj_on f A ==> f ` A = A"
2141 by (simp add: card_seteq card_image)
2143 lemma eq_card_imp_inj_on:
2144 "[| finite A; card(f ` A) = card A |] ==> inj_on f A"
2145 apply (induct rule:finite_induct)
2147 apply(frule card_image_le[where f = f])
2148 apply(simp add:card_insert_if split:if_splits)
2151 lemma inj_on_iff_eq_card:
2152 "finite A ==> inj_on f A = (card(f ` A) = card A)"
2153 by(blast intro: card_image eq_card_imp_inj_on)
2156 lemma card_inj_on_le:
2157 "[|inj_on f A; f ` A \<subseteq> B; finite B |] ==> card A \<le> card B"
2158 apply (subgoal_tac "finite A")
2159 apply (force intro: card_mono simp add: card_image [symmetric])
2160 apply (blast intro: finite_imageD dest: finite_subset)
2164 "[|inj_on f A; f ` A \<subseteq> B; inj_on g B; g ` B \<subseteq> A;
2165 finite A; finite B |] ==> card A = card B"
2166 by (auto intro: le_anti_sym card_inj_on_le)
2169 subsubsection {* Cardinality of products *}
2172 lemma SigmaI_insert: "y \<notin> A ==>
2173 (SIGMA x:(insert y A). B x) = (({y} <*> (B y)) \<union> (SIGMA x: A. B x))"
2177 lemma card_SigmaI [simp]:
2178 "\<lbrakk> finite A; ALL a:A. finite (B a) \<rbrakk>
2179 \<Longrightarrow> card (SIGMA x: A. B x) = (\<Sum>a\<in>A. card (B a))"
2180 by(simp add:card_def setsum_Sigma del:setsum_constant)
2182 lemma card_cartesian_product: "card (A <*> B) = card(A) * card(B)"
2183 apply (cases "finite A")
2184 apply (cases "finite B")
2185 apply (auto simp add: card_eq_0_iff
2186 dest: finite_cartesian_productD1 finite_cartesian_productD2)
2189 lemma card_cartesian_product_singleton: "card({x} <*> A) = card(A)"
2190 by (simp add: card_cartesian_product)
2193 subsubsection {* Cardinality of sums *}
2196 assumes "finite A" and "finite B"
2197 shows "card (A <+> B) = card A + card B"
2199 have "Inl`A \<inter> Inr`B = {}" by fast
2200 with assms show ?thesis
2202 by (simp add: card_Un_disjoint card_image)
2206 subsubsection {* Cardinality of the Powerset *}
2208 lemma card_Pow: "finite A ==> card (Pow A) = Suc (Suc 0) ^ card A" (* FIXME numeral 2 (!?) *)
2209 apply (induct set: finite)
2210 apply (simp_all add: Pow_insert)
2211 apply (subst card_Un_disjoint, blast)
2212 apply (blast intro: finite_imageI, blast)
2213 apply (subgoal_tac "inj_on (insert x) (Pow F)")
2214 apply (simp add: card_image Pow_insert)
2215 apply (unfold inj_on_def)
2216 apply (blast elim!: equalityE)
2219 text {* Relates to equivalence classes. Based on a theorem of F. Kammüller. *}
2221 lemma dvd_partition:
2222 "finite (Union C) ==>
2223 ALL c : C. k dvd card c ==>
2224 (ALL c1: C. ALL c2: C. c1 \<noteq> c2 --> c1 Int c2 = {}) ==>
2225 k dvd card (Union C)"
2226 apply(frule finite_UnionD)
2227 apply(rotate_tac -1)
2228 apply (induct set: finite, simp_all, clarify)
2229 apply (subst card_Un_disjoint)
2230 apply (auto simp add: dvd_add disjoint_eq_subset_Compl)
2234 subsubsection {* Relating injectivity and surjectivity *}
2236 lemma finite_surj_inj: "finite(A) \<Longrightarrow> A <= f`A \<Longrightarrow> inj_on f A"
2237 apply(rule eq_card_imp_inj_on, assumption)
2238 apply(frule finite_imageI)
2239 apply(drule (1) card_seteq)
2240 apply(erule card_image_le)
2244 lemma finite_UNIV_surj_inj: fixes f :: "'a \<Rightarrow> 'a"
2245 shows "finite(UNIV:: 'a set) \<Longrightarrow> surj f \<Longrightarrow> inj f"
2246 by (blast intro: finite_surj_inj subset_UNIV dest:surj_range)
2248 lemma finite_UNIV_inj_surj: fixes f :: "'a \<Rightarrow> 'a"
2249 shows "finite(UNIV:: 'a set) \<Longrightarrow> inj f \<Longrightarrow> surj f"
2250 by(fastsimp simp:surj_def dest!: endo_inj_surj)
2252 corollary infinite_UNIV_nat: "~finite(UNIV::nat set)"
2254 assume "finite(UNIV::nat set)"
2255 with finite_UNIV_inj_surj[of Suc]
2256 show False by simp (blast dest: Suc_neq_Zero surjD)
2259 lemma infinite_UNIV_char_0:
2260 "\<not> finite (UNIV::'a::semiring_char_0 set)"
2262 assume "finite (UNIV::'a set)"
2263 with subset_UNIV have "finite (range of_nat::'a set)"
2264 by (rule finite_subset)
2265 moreover have "inj (of_nat::nat \<Rightarrow> 'a)"
2266 by (simp add: inj_on_def)
2267 ultimately have "finite (UNIV::nat set)"
2268 by (rule finite_imageD)
2270 by (simp add: infinite_UNIV_nat)
2273 subsection{* A fold functional for non-empty sets *}
2275 text{* Does not require start value. *}
2278 fold1Set :: "('a => 'a => 'a) => 'a set => 'a => bool"
2279 for f :: "'a => 'a => 'a"
2281 fold1Set_insertI [intro]:
2282 "\<lbrakk> fold_graph f a A x; a \<notin> A \<rbrakk> \<Longrightarrow> fold1Set f (insert a A) x"
2285 fold1 :: "('a => 'a => 'a) => 'a set => 'a"
2286 "fold1 f A == THE x. fold1Set f A x"
2288 lemma fold1Set_nonempty:
2289 "fold1Set f A x \<Longrightarrow> A \<noteq> {}"
2290 by(erule fold1Set.cases, simp_all)
2292 inductive_cases empty_fold1SetE [elim!]: "fold1Set f {} x"
2294 inductive_cases insert_fold1SetE [elim!]: "fold1Set f (insert a X) x"
2297 lemma fold1Set_sing [iff]: "(fold1Set f {a} b) = (a = b)"
2298 by (blast intro: fold_graph.intros elim: fold_graph.cases)
2300 lemma fold1_singleton [simp]: "fold1 f {a} = a"
2301 by (unfold fold1_def) blast
2303 lemma finite_nonempty_imp_fold1Set:
2304 "\<lbrakk> finite A; A \<noteq> {} \<rbrakk> \<Longrightarrow> EX x. fold1Set f A x"
2305 apply (induct A rule: finite_induct)
2306 apply (auto dest: finite_imp_fold_graph [of _ f])
2309 text{*First, some lemmas about @{const fold_graph}.*}
2311 context ab_semigroup_mult
2314 lemma fun_left_comm: "fun_left_comm(op *)"
2315 by unfold_locales (simp add: mult_ac)
2317 lemma fold_graph_insert_swap:
2318 assumes fold: "fold_graph times (b::'a) A y" and "b \<notin> A"
2319 shows "fold_graph times z (insert b A) (z * y)"
2321 interpret fun_left_comm "op *::'a \<Rightarrow> 'a \<Rightarrow> 'a" by (rule fun_left_comm)
2322 from assms show ?thesis
2323 proof (induct rule: fold_graph.induct)
2324 case emptyI thus ?case by (force simp add: fold_insert_aux mult_commute)
2326 case (insertI x A y)
2327 have "fold_graph times z (insert x (insert b A)) (x * (z * y))"
2328 using insertI by force --{*how does @{term id} get unfolded?*}
2329 thus ?case by (simp add: insert_commute mult_ac)
2333 lemma fold_graph_permute_diff:
2334 assumes fold: "fold_graph times b A x"
2335 shows "!!a. \<lbrakk>a \<in> A; b \<notin> A\<rbrakk> \<Longrightarrow> fold_graph times a (insert b (A-{a})) x"
2337 proof (induct rule: fold_graph.induct)
2338 case emptyI thus ?case by simp
2340 case (insertI x A y)
2341 have "a = x \<or> a \<in> A" using insertI by simp
2345 with insertI show ?thesis
2346 by (simp add: id_def [symmetric], blast intro: fold_graph_insert_swap)
2348 assume ainA: "a \<in> A"
2349 hence "fold_graph times a (insert x (insert b (A - {a}))) (x * y)"
2350 using insertI by force
2352 have "insert x (insert b (A - {a})) = insert b (insert x A - {a})"
2353 using ainA insertI by blast
2354 ultimately show ?thesis by simp
2358 lemma fold1_eq_fold:
2359 assumes "finite A" "a \<notin> A" shows "fold1 times (insert a A) = fold times a A"
2361 interpret fun_left_comm "op *::'a \<Rightarrow> 'a \<Rightarrow> 'a" by (rule fun_left_comm)
2362 from assms show ?thesis
2363 apply (simp add: fold1_def fold_def)
2364 apply (rule the_equality)
2365 apply (best intro: fold_graph_determ theI dest: finite_imp_fold_graph [of _ times])
2366 apply (rule sym, clarify)
2367 apply (case_tac "Aa=A")
2368 apply (best intro: the_equality fold_graph_determ)
2369 apply (subgoal_tac "fold_graph times a A x")
2370 apply (best intro: the_equality fold_graph_determ)
2371 apply (subgoal_tac "insert aa (Aa - {a}) = A")
2372 prefer 2 apply (blast elim: equalityE)
2373 apply (auto dest: fold_graph_permute_diff [where a=a])
2377 lemma nonempty_iff: "(A \<noteq> {}) = (\<exists>x B. A = insert x B & x \<notin> B)"
2380 apply (drule_tac x=x in spec)
2381 apply (drule_tac x="A-{x}" in spec, auto)
2385 assumes nonempty: "A \<noteq> {}" and A: "finite A" "x \<notin> A"
2386 shows "fold1 times (insert x A) = x * fold1 times A"
2388 interpret fun_left_comm "op *::'a \<Rightarrow> 'a \<Rightarrow> 'a" by (rule fun_left_comm)
2389 from nonempty obtain a A' where "A = insert a A' & a ~: A'"
2390 by (auto simp add: nonempty_iff)
2392 by (simp add: insert_commute [of x] fold1_eq_fold eq_commute)
2397 context ab_semigroup_idem_mult
2400 lemma fun_left_comm_idem: "fun_left_comm_idem(op *)"
2401 apply unfold_locales
2402 apply (simp add: mult_ac)
2403 apply (simp add: mult_idem mult_assoc[symmetric])
2407 lemma fold1_insert_idem [simp]:
2408 assumes nonempty: "A \<noteq> {}" and A: "finite A"
2409 shows "fold1 times (insert x A) = x * fold1 times A"
2411 interpret fun_left_comm_idem "op *::'a \<Rightarrow> 'a \<Rightarrow> 'a"
2412 by (rule fun_left_comm_idem)
2413 from nonempty obtain a A' where A': "A = insert a A' & a ~: A'"
2414 by (auto simp add: nonempty_iff)
2421 with prems show ?thesis by (simp add: mult_idem)
2423 assume "A' \<noteq> {}"
2424 with prems show ?thesis
2425 by (simp add: fold1_insert mult_assoc [symmetric] mult_idem)
2428 assume "a \<noteq> x"
2429 with prems show ?thesis
2430 by (simp add: insert_commute fold1_eq_fold fold_insert_idem)
2434 lemma hom_fold1_commute:
2435 assumes hom: "!!x y. h (x * y) = h x * h y"
2436 and N: "finite N" "N \<noteq> {}" shows "h (fold1 times N) = fold1 times (h ` N)"
2437 using N proof (induct rule: finite_ne_induct)
2438 case singleton thus ?case by simp
2441 then have "h (fold1 times (insert n N)) = h (n * fold1 times N)" by simp
2442 also have "\<dots> = h n * h (fold1 times N)" by(rule hom)
2443 also have "h (fold1 times N) = fold1 times (h ` N)" by(rule insert)
2444 also have "times (h n) \<dots> = fold1 times (insert (h n) (h ` N))"
2445 using insert by(simp)
2446 also have "insert (h n) (h ` N) = h ` insert n N" by simp
2447 finally show ?case .
2453 text{* Now the recursion rules for definitions: *}
2455 lemma fold1_singleton_def: "g = fold1 f \<Longrightarrow> g {a} = a"
2456 by(simp add:fold1_singleton)
2458 lemma (in ab_semigroup_mult) fold1_insert_def:
2459 "\<lbrakk> g = fold1 times; finite A; x \<notin> A; A \<noteq> {} \<rbrakk> \<Longrightarrow> g (insert x A) = x * g A"
2460 by (simp add:fold1_insert)
2462 lemma (in ab_semigroup_idem_mult) fold1_insert_idem_def:
2463 "\<lbrakk> g = fold1 times; finite A; A \<noteq> {} \<rbrakk> \<Longrightarrow> g (insert x A) = x * g A"
2466 subsubsection{* Determinacy for @{term fold1Set} *}
2468 (*Not actually used!!*)
2470 context ab_semigroup_mult
2473 lemma fold_graph_permute:
2474 "[|fold_graph times id b (insert a A) x; a \<notin> A; b \<notin> A|]
2475 ==> fold_graph times id a (insert b A) x"
2477 apply (auto dest: fold_graph_permute_diff)
2480 lemma fold1Set_determ:
2481 "fold1Set times A x ==> fold1Set times A y ==> y = x"
2482 proof (clarify elim!: fold1Set.cases)
2484 assume Ax: "fold_graph times id a A x"
2485 assume By: "fold_graph times id b B y"
2486 assume anotA: "a \<notin> A"
2487 assume bnotB: "b \<notin> B"
2488 assume eq: "insert a A = insert b B"
2492 hence "A=B" using anotA bnotB eq by (blast elim!: equalityE)
2493 thus ?thesis using Ax By same by (blast intro: fold_graph_determ)
2495 assume diff: "a\<noteq>b"
2497 have B: "B = insert a ?D" and A: "A = insert b ?D"
2498 and aB: "a \<in> B" and bA: "b \<in> A"
2499 using eq anotA bnotB diff by (blast elim!:equalityE)+
2501 have "fold_graph times id a (insert b ?D) y"
2502 by (auto intro: fold_graph_permute simp add: insert_absorb)
2504 have "fold_graph times id a (insert b ?D) x"
2505 by (simp add: A [symmetric] Ax)
2506 ultimately show ?thesis by (blast intro: fold_graph_determ)
2510 lemma fold1Set_equality: "fold1Set times A y ==> fold1 times A = y"
2511 by (unfold fold1_def) (blast intro: fold1Set_determ)
2517 empty_fold_graphE [rule del] fold_graph.intros [rule del]
2518 empty_fold1SetE [rule del] insert_fold1SetE [rule del]
2519 -- {* No more proofs involve these relations. *}
2521 subsubsection {* Lemmas about @{text fold1} *}
2523 context ab_semigroup_mult
2527 assumes A: "finite A" "A \<noteq> {}"
2528 shows "finite B \<Longrightarrow> B \<noteq> {} \<Longrightarrow> A Int B = {} \<Longrightarrow>
2529 fold1 times (A Un B) = fold1 times A * fold1 times B"
2530 using A by (induct rule: finite_ne_induct)
2531 (simp_all add: fold1_insert mult_assoc)
2534 assumes A: "finite (A)" "A \<noteq> {}" and elem: "\<And>x y. x * y \<in> {x,y}"
2535 shows "fold1 times A \<in> A"
2537 proof (induct rule:finite_ne_induct)
2538 case singleton thus ?case by simp
2540 case insert thus ?case using elem by (force simp add:fold1_insert)
2545 lemma (in ab_semigroup_idem_mult) fold1_Un2:
2546 assumes A: "finite A" "A \<noteq> {}"
2547 shows "finite B \<Longrightarrow> B \<noteq> {} \<Longrightarrow>
2548 fold1 times (A Un B) = fold1 times A * fold1 times B"
2550 proof(induct rule:finite_ne_induct)
2551 case singleton thus ?case by simp
2553 case insert thus ?case by (simp add: mult_assoc)
2557 subsubsection {* Fold1 in lattices with @{const inf} and @{const sup} *}
2560 As an application of @{text fold1} we define infimum
2561 and supremum in (not necessarily complete!) lattices
2562 over (non-empty) sets by means of @{text fold1}.
2565 context lower_semilattice
2568 lemma ab_semigroup_idem_mult_inf:
2569 "ab_semigroup_idem_mult inf"
2570 proof qed (rule inf_assoc inf_commute inf_idem)+
2572 lemma below_fold1_iff:
2573 assumes "finite A" "A \<noteq> {}"
2574 shows "x \<le> fold1 inf A \<longleftrightarrow> (\<forall>a\<in>A. x \<le> a)"
2576 interpret ab_semigroup_idem_mult inf
2577 by (rule ab_semigroup_idem_mult_inf)
2578 show ?thesis using assms by (induct rule: finite_ne_induct) simp_all
2584 shows "fold1 inf A \<le> a"
2586 from assms have "A \<noteq> {}" by auto
2587 from `finite A` `A \<noteq> {}` `a \<in> A` show ?thesis
2588 proof (induct rule: finite_ne_induct)
2589 case singleton thus ?case by simp
2591 interpret ab_semigroup_idem_mult inf
2592 by (rule ab_semigroup_idem_mult_inf)
2594 from insert(5) have "a = x \<or> a \<in> F" by simp
2597 assume "a = x" thus ?thesis using insert
2598 by (simp add: mult_ac)
2601 hence bel: "fold1 inf F \<le> a" by (rule insert)
2602 have "inf (fold1 inf (insert x F)) a = inf x (inf (fold1 inf F) a)"
2603 using insert by (simp add: mult_ac)
2604 also have "inf (fold1 inf F) a = fold1 inf F"
2605 using bel by (auto intro: antisym)
2606 also have "inf x \<dots> = fold1 inf (insert x F)"
2607 using insert by (simp add: mult_ac)
2608 finally have aux: "inf (fold1 inf (insert x F)) a = fold1 inf (insert x F)" .
2609 moreover have "inf (fold1 inf (insert x F)) a \<le> a" by simp
2610 ultimately show ?thesis by simp
2617 lemma (in upper_semilattice) ab_semigroup_idem_mult_sup:
2618 "ab_semigroup_idem_mult sup"
2619 by (rule lower_semilattice.ab_semigroup_idem_mult_inf)
2626 Inf_fin :: "'a set \<Rightarrow> 'a" ("\<Sqinter>\<^bsub>fin\<^esub>_" [900] 900)
2628 "Inf_fin = fold1 inf"
2631 Sup_fin :: "'a set \<Rightarrow> 'a" ("\<Squnion>\<^bsub>fin\<^esub>_" [900] 900)
2633 "Sup_fin = fold1 sup"
2635 lemma Inf_le_Sup [simp]: "\<lbrakk> finite A; A \<noteq> {} \<rbrakk> \<Longrightarrow> \<Sqinter>\<^bsub>fin\<^esub>A \<le> \<Squnion>\<^bsub>fin\<^esub>A"
2636 apply(unfold Sup_fin_def Inf_fin_def)
2637 apply(subgoal_tac "EX a. a:A")
2638 prefer 2 apply blast
2640 apply(rule order_trans)
2641 apply(erule (1) fold1_belowI)
2642 apply(erule (1) lower_semilattice.fold1_belowI [OF dual_lattice])
2645 lemma sup_Inf_absorb [simp]:
2646 "finite A \<Longrightarrow> a \<in> A \<Longrightarrow> sup a (\<Sqinter>\<^bsub>fin\<^esub>A) = a"
2647 apply(subst sup_commute)
2648 apply(simp add: Inf_fin_def sup_absorb2 fold1_belowI)
2651 lemma inf_Sup_absorb [simp]:
2652 "finite A \<Longrightarrow> a \<in> A \<Longrightarrow> inf a (\<Squnion>\<^bsub>fin\<^esub>A) = a"
2653 by (simp add: Sup_fin_def inf_absorb1
2654 lower_semilattice.fold1_belowI [OF dual_lattice])
2658 context distrib_lattice
2661 lemma sup_Inf1_distrib:
2664 shows "sup x (\<Sqinter>\<^bsub>fin\<^esub>A) = \<Sqinter>\<^bsub>fin\<^esub>{sup x a|a. a \<in> A}"
2666 interpret ab_semigroup_idem_mult inf
2667 by (rule ab_semigroup_idem_mult_inf)
2668 from assms show ?thesis
2669 by (simp add: Inf_fin_def image_def
2670 hom_fold1_commute [where h="sup x", OF sup_inf_distrib1])
2671 (rule arg_cong [where f="fold1 inf"], blast)
2674 lemma sup_Inf2_distrib:
2675 assumes A: "finite A" "A \<noteq> {}" and B: "finite B" "B \<noteq> {}"
2676 shows "sup (\<Sqinter>\<^bsub>fin\<^esub>A) (\<Sqinter>\<^bsub>fin\<^esub>B) = \<Sqinter>\<^bsub>fin\<^esub>{sup a b|a b. a \<in> A \<and> b \<in> B}"
2677 using A proof (induct rule: finite_ne_induct)
2678 case singleton thus ?case
2679 by (simp add: sup_Inf1_distrib [OF B] fold1_singleton_def [OF Inf_fin_def])
2681 interpret ab_semigroup_idem_mult inf
2682 by (rule ab_semigroup_idem_mult_inf)
2684 have finB: "finite {sup x b |b. b \<in> B}"
2685 by(rule finite_surj[where f = "sup x", OF B(1)], auto)
2686 have finAB: "finite {sup a b |a b. a \<in> A \<and> b \<in> B}"
2688 have "{sup a b |a b. a \<in> A \<and> b \<in> B} = (UN a:A. UN b:B. {sup a b})"
2690 thus ?thesis by(simp add: insert(1) B(1))
2692 have ne: "{sup a b |a b. a \<in> A \<and> b \<in> B} \<noteq> {}" using insert B by blast
2693 have "sup (\<Sqinter>\<^bsub>fin\<^esub>(insert x A)) (\<Sqinter>\<^bsub>fin\<^esub>B) = sup (inf x (\<Sqinter>\<^bsub>fin\<^esub>A)) (\<Sqinter>\<^bsub>fin\<^esub>B)"
2694 using insert by (simp add: fold1_insert_idem_def [OF Inf_fin_def])
2695 also have "\<dots> = inf (sup x (\<Sqinter>\<^bsub>fin\<^esub>B)) (sup (\<Sqinter>\<^bsub>fin\<^esub>A) (\<Sqinter>\<^bsub>fin\<^esub>B))" by(rule sup_inf_distrib2)
2696 also have "\<dots> = inf (\<Sqinter>\<^bsub>fin\<^esub>{sup x b|b. b \<in> B}) (\<Sqinter>\<^bsub>fin\<^esub>{sup a b|a b. a \<in> A \<and> b \<in> B})"
2697 using insert by(simp add:sup_Inf1_distrib[OF B])
2698 also have "\<dots> = \<Sqinter>\<^bsub>fin\<^esub>({sup x b |b. b \<in> B} \<union> {sup a b |a b. a \<in> A \<and> b \<in> B})"
2699 (is "_ = \<Sqinter>\<^bsub>fin\<^esub>?M")
2701 by (simp add: Inf_fin_def fold1_Un2 [OF finB _ finAB ne])
2702 also have "?M = {sup a b |a b. a \<in> insert x A \<and> b \<in> B}"
2704 finally show ?case .
2707 lemma inf_Sup1_distrib:
2708 assumes "finite A" and "A \<noteq> {}"
2709 shows "inf x (\<Squnion>\<^bsub>fin\<^esub>A) = \<Squnion>\<^bsub>fin\<^esub>{inf x a|a. a \<in> A}"
2711 interpret ab_semigroup_idem_mult sup
2712 by (rule ab_semigroup_idem_mult_sup)
2713 from assms show ?thesis
2714 by (simp add: Sup_fin_def image_def hom_fold1_commute [where h="inf x", OF inf_sup_distrib1])
2715 (rule arg_cong [where f="fold1 sup"], blast)
2718 lemma inf_Sup2_distrib:
2719 assumes A: "finite A" "A \<noteq> {}" and B: "finite B" "B \<noteq> {}"
2720 shows "inf (\<Squnion>\<^bsub>fin\<^esub>A) (\<Squnion>\<^bsub>fin\<^esub>B) = \<Squnion>\<^bsub>fin\<^esub>{inf a b|a b. a \<in> A \<and> b \<in> B}"
2721 using A proof (induct rule: finite_ne_induct)
2722 case singleton thus ?case
2723 by(simp add: inf_Sup1_distrib [OF B] fold1_singleton_def [OF Sup_fin_def])
2726 have finB: "finite {inf x b |b. b \<in> B}"
2727 by(rule finite_surj[where f = "%b. inf x b", OF B(1)], auto)
2728 have finAB: "finite {inf a b |a b. a \<in> A \<and> b \<in> B}"
2730 have "{inf a b |a b. a \<in> A \<and> b \<in> B} = (UN a:A. UN b:B. {inf a b})"
2732 thus ?thesis by(simp add: insert(1) B(1))
2734 have ne: "{inf a b |a b. a \<in> A \<and> b \<in> B} \<noteq> {}" using insert B by blast
2735 interpret ab_semigroup_idem_mult sup
2736 by (rule ab_semigroup_idem_mult_sup)
2737 have "inf (\<Squnion>\<^bsub>fin\<^esub>(insert x A)) (\<Squnion>\<^bsub>fin\<^esub>B) = inf (sup x (\<Squnion>\<^bsub>fin\<^esub>A)) (\<Squnion>\<^bsub>fin\<^esub>B)"
2738 using insert by (simp add: fold1_insert_idem_def [OF Sup_fin_def])
2739 also have "\<dots> = sup (inf x (\<Squnion>\<^bsub>fin\<^esub>B)) (inf (\<Squnion>\<^bsub>fin\<^esub>A) (\<Squnion>\<^bsub>fin\<^esub>B))" by(rule inf_sup_distrib2)
2740 also have "\<dots> = sup (\<Squnion>\<^bsub>fin\<^esub>{inf x b|b. b \<in> B}) (\<Squnion>\<^bsub>fin\<^esub>{inf a b|a b. a \<in> A \<and> b \<in> B})"
2741 using insert by(simp add:inf_Sup1_distrib[OF B])
2742 also have "\<dots> = \<Squnion>\<^bsub>fin\<^esub>({inf x b |b. b \<in> B} \<union> {inf a b |a b. a \<in> A \<and> b \<in> B})"
2743 (is "_ = \<Squnion>\<^bsub>fin\<^esub>?M")
2745 by (simp add: Sup_fin_def fold1_Un2 [OF finB _ finAB ne])
2746 also have "?M = {inf a b |a b. a \<in> insert x A \<and> b \<in> B}"
2748 finally show ?case .
2753 context complete_lattice
2757 Coincidence on finite sets in complete lattices:
2761 assumes "finite A" and "A \<noteq> {}"
2762 shows "\<Sqinter>\<^bsub>fin\<^esub>A = Inf A"
2764 interpret ab_semigroup_idem_mult inf
2765 by (rule ab_semigroup_idem_mult_inf)
2766 from assms show ?thesis
2767 unfolding Inf_fin_def by (induct A set: finite)
2768 (simp_all add: Inf_insert_simp)
2772 assumes "finite A" and "A \<noteq> {}"
2773 shows "\<Squnion>\<^bsub>fin\<^esub>A = Sup A"
2775 interpret ab_semigroup_idem_mult sup
2776 by (rule ab_semigroup_idem_mult_sup)
2777 from assms show ?thesis
2778 unfolding Sup_fin_def by (induct A set: finite)
2779 (simp_all add: Sup_insert_simp)
2785 subsubsection {* Fold1 in linear orders with @{const min} and @{const max} *}
2788 As an application of @{text fold1} we define minimum
2789 and maximum in (not necessarily complete!) linear orders
2790 over (non-empty) sets by means of @{text fold1}.
2796 lemma ab_semigroup_idem_mult_min:
2797 "ab_semigroup_idem_mult min"
2798 proof qed (auto simp add: min_def)
2800 lemma ab_semigroup_idem_mult_max:
2801 "ab_semigroup_idem_mult max"
2802 proof qed (auto simp add: max_def)
2805 "lower_semilattice (op \<le>) (op <) min"
2806 proof qed (auto simp add: min_def)
2809 "lower_semilattice (op \<ge>) (op >) max"
2810 proof qed (auto simp add: max_def)
2813 "ord.max (op \<ge>) = min"
2814 by (auto simp add: ord.max_def_raw min_def_raw expand_fun_eq)
2817 "ord.min (op \<ge>) = max"
2818 by (auto simp add: ord.min_def_raw max_def_raw expand_fun_eq)
2820 lemma strict_below_fold1_iff:
2821 assumes "finite A" and "A \<noteq> {}"
2822 shows "x < fold1 min A \<longleftrightarrow> (\<forall>a\<in>A. x < a)"
2824 interpret ab_semigroup_idem_mult min
2825 by (rule ab_semigroup_idem_mult_min)
2826 from assms show ?thesis
2827 by (induct rule: finite_ne_induct)
2828 (simp_all add: fold1_insert)
2831 lemma fold1_below_iff:
2832 assumes "finite A" and "A \<noteq> {}"
2833 shows "fold1 min A \<le> x \<longleftrightarrow> (\<exists>a\<in>A. a \<le> x)"
2835 interpret ab_semigroup_idem_mult min
2836 by (rule ab_semigroup_idem_mult_min)
2837 from assms show ?thesis
2838 by (induct rule: finite_ne_induct)
2839 (simp_all add: fold1_insert min_le_iff_disj)
2842 lemma fold1_strict_below_iff:
2843 assumes "finite A" and "A \<noteq> {}"
2844 shows "fold1 min A < x \<longleftrightarrow> (\<exists>a\<in>A. a < x)"
2846 interpret ab_semigroup_idem_mult min
2847 by (rule ab_semigroup_idem_mult_min)
2848 from assms show ?thesis
2849 by (induct rule: finite_ne_induct)
2850 (simp_all add: fold1_insert min_less_iff_disj)
2853 lemma fold1_antimono:
2854 assumes "A \<noteq> {}" and "A \<subseteq> B" and "finite B"
2855 shows "fold1 min B \<le> fold1 min A"
2857 assume "A = B" thus ?thesis by simp
2859 interpret ab_semigroup_idem_mult min
2860 by (rule ab_semigroup_idem_mult_min)
2861 assume "A \<noteq> B"
2862 have B: "B = A \<union> (B-A)" using `A \<subseteq> B` by blast
2863 have "fold1 min B = fold1 min (A \<union> (B-A))" by(subst B)(rule refl)
2864 also have "\<dots> = min (fold1 min A) (fold1 min (B-A))"
2866 have "finite A" by(rule finite_subset[OF `A \<subseteq> B` `finite B`])
2867 moreover have "finite(B-A)" by(rule finite_Diff[OF `finite B`]) (* by(blast intro:finite_Diff prems) fails *)
2868 moreover have "(B-A) \<noteq> {}" using prems by blast
2869 moreover have "A Int (B-A) = {}" using prems by blast
2870 ultimately show ?thesis using `A \<noteq> {}` by (rule_tac fold1_Un)
2872 also have "\<dots> \<le> fold1 min A" by (simp add: min_le_iff_disj)
2873 finally show ?thesis .
2877 Min :: "'a set \<Rightarrow> 'a"
2882 Max :: "'a set \<Rightarrow> 'a"
2886 lemmas Min_singleton [simp] = fold1_singleton_def [OF Min_def]
2887 lemmas Max_singleton [simp] = fold1_singleton_def [OF Max_def]
2889 lemma Min_insert [simp]:
2890 assumes "finite A" and "A \<noteq> {}"
2891 shows "Min (insert x A) = min x (Min A)"
2893 interpret ab_semigroup_idem_mult min
2894 by (rule ab_semigroup_idem_mult_min)
2895 from assms show ?thesis by (rule fold1_insert_idem_def [OF Min_def])
2898 lemma Max_insert [simp]:
2899 assumes "finite A" and "A \<noteq> {}"
2900 shows "Max (insert x A) = max x (Max A)"
2902 interpret ab_semigroup_idem_mult max
2903 by (rule ab_semigroup_idem_mult_max)
2904 from assms show ?thesis by (rule fold1_insert_idem_def [OF Max_def])
2907 lemma Min_in [simp]:
2908 assumes "finite A" and "A \<noteq> {}"
2909 shows "Min A \<in> A"
2911 interpret ab_semigroup_idem_mult min
2912 by (rule ab_semigroup_idem_mult_min)
2913 from assms fold1_in show ?thesis by (fastsimp simp: Min_def min_def)
2916 lemma Max_in [simp]:
2917 assumes "finite A" and "A \<noteq> {}"
2918 shows "Max A \<in> A"
2920 interpret ab_semigroup_idem_mult max
2921 by (rule ab_semigroup_idem_mult_max)
2922 from assms fold1_in [of A] show ?thesis by (fastsimp simp: Max_def max_def)
2926 assumes "finite A" and "A \<noteq> {}" and "finite B" and "B \<noteq> {}"
2927 shows "Min (A \<union> B) = min (Min A) (Min B)"
2929 interpret ab_semigroup_idem_mult min
2930 by (rule ab_semigroup_idem_mult_min)
2931 from assms show ?thesis
2932 by (simp add: Min_def fold1_Un2)
2936 assumes "finite A" and "A \<noteq> {}" and "finite B" and "B \<noteq> {}"
2937 shows "Max (A \<union> B) = max (Max A) (Max B)"
2939 interpret ab_semigroup_idem_mult max
2940 by (rule ab_semigroup_idem_mult_max)
2941 from assms show ?thesis
2942 by (simp add: Max_def fold1_Un2)
2945 lemma hom_Min_commute:
2946 assumes "\<And>x y. h (min x y) = min (h x) (h y)"
2947 and "finite N" and "N \<noteq> {}"
2948 shows "h (Min N) = Min (h ` N)"
2950 interpret ab_semigroup_idem_mult min
2951 by (rule ab_semigroup_idem_mult_min)
2952 from assms show ?thesis
2953 by (simp add: Min_def hom_fold1_commute)
2956 lemma hom_Max_commute:
2957 assumes "\<And>x y. h (max x y) = max (h x) (h y)"
2958 and "finite N" and "N \<noteq> {}"
2959 shows "h (Max N) = Max (h ` N)"
2961 interpret ab_semigroup_idem_mult max
2962 by (rule ab_semigroup_idem_mult_max)
2963 from assms show ?thesis
2964 by (simp add: Max_def hom_fold1_commute [of h])
2967 lemma Min_le [simp]:
2968 assumes "finite A" and "x \<in> A"
2969 shows "Min A \<le> x"
2971 interpret lower_semilattice "op \<le>" "op <" min
2972 by (rule min_lattice)
2973 from assms show ?thesis by (simp add: Min_def fold1_belowI)
2976 lemma Max_ge [simp]:
2977 assumes "finite A" and "x \<in> A"
2978 shows "x \<le> Max A"
2980 interpret lower_semilattice "op \<ge>" "op >" max
2981 by (rule max_lattice)
2982 from assms show ?thesis by (simp add: Max_def fold1_belowI)
2985 lemma Min_ge_iff [simp, noatp]:
2986 assumes "finite A" and "A \<noteq> {}"
2987 shows "x \<le> Min A \<longleftrightarrow> (\<forall>a\<in>A. x \<le> a)"
2989 interpret lower_semilattice "op \<le>" "op <" min
2990 by (rule min_lattice)
2991 from assms show ?thesis by (simp add: Min_def below_fold1_iff)
2994 lemma Max_le_iff [simp, noatp]:
2995 assumes "finite A" and "A \<noteq> {}"
2996 shows "Max A \<le> x \<longleftrightarrow> (\<forall>a\<in>A. a \<le> x)"
2998 interpret lower_semilattice "op \<ge>" "op >" max
2999 by (rule max_lattice)
3000 from assms show ?thesis by (simp add: Max_def below_fold1_iff)
3003 lemma Min_gr_iff [simp, noatp]:
3004 assumes "finite A" and "A \<noteq> {}"
3005 shows "x < Min A \<longleftrightarrow> (\<forall>a\<in>A. x < a)"
3007 interpret lower_semilattice "op \<le>" "op <" min
3008 by (rule min_lattice)
3009 from assms show ?thesis by (simp add: Min_def strict_below_fold1_iff)
3012 lemma Max_less_iff [simp, noatp]:
3013 assumes "finite A" and "A \<noteq> {}"
3014 shows "Max A < x \<longleftrightarrow> (\<forall>a\<in>A. a < x)"
3017 interpret linorder "op \<ge>" "op >"
3018 by (rule dual_linorder)
3019 from assms show ?thesis
3020 by (simp add: Max strict_below_fold1_iff [folded dual_max])
3023 lemma Min_le_iff [noatp]:
3024 assumes "finite A" and "A \<noteq> {}"
3025 shows "Min A \<le> x \<longleftrightarrow> (\<exists>a\<in>A. a \<le> x)"
3027 interpret lower_semilattice "op \<le>" "op <" min
3028 by (rule min_lattice)
3029 from assms show ?thesis
3030 by (simp add: Min_def fold1_below_iff)
3033 lemma Max_ge_iff [noatp]:
3034 assumes "finite A" and "A \<noteq> {}"
3035 shows "x \<le> Max A \<longleftrightarrow> (\<exists>a\<in>A. x \<le> a)"
3038 interpret linorder "op \<ge>" "op >"
3039 by (rule dual_linorder)
3040 from assms show ?thesis
3041 by (simp add: Max fold1_below_iff [folded dual_max])
3044 lemma Min_less_iff [noatp]:
3045 assumes "finite A" and "A \<noteq> {}"
3046 shows "Min A < x \<longleftrightarrow> (\<exists>a\<in>A. a < x)"
3048 interpret lower_semilattice "op \<le>" "op <" min
3049 by (rule min_lattice)
3050 from assms show ?thesis
3051 by (simp add: Min_def fold1_strict_below_iff)
3054 lemma Max_gr_iff [noatp]:
3055 assumes "finite A" and "A \<noteq> {}"
3056 shows "x < Max A \<longleftrightarrow> (\<exists>a\<in>A. x < a)"
3059 interpret linorder "op \<ge>" "op >"
3060 by (rule dual_linorder)
3061 from assms show ?thesis
3062 by (simp add: Max fold1_strict_below_iff [folded dual_max])
3067 assumes "\<And>y. y \<in> A \<Longrightarrow> y \<ge> x"
3070 proof (rule antisym)
3071 from `x \<in> A` have "A \<noteq> {}" by auto
3072 with assms show "Min A \<ge> x" by simp
3074 from assms show "x \<ge> Min A" by simp
3079 assumes "\<And>y. y \<in> A \<Longrightarrow> y \<le> x"
3082 proof (rule antisym)
3083 from `x \<in> A` have "A \<noteq> {}" by auto
3084 with assms show "Max A \<le> x" by simp
3086 from assms show "x \<le> Max A" by simp
3090 assumes "M \<subseteq> N" and "M \<noteq> {}" and "finite N"
3091 shows "Min N \<le> Min M"
3093 interpret distrib_lattice "op \<le>" "op <" min max
3094 by (rule distrib_lattice_min_max)
3095 from assms show ?thesis by (simp add: Min_def fold1_antimono)
3099 assumes "M \<subseteq> N" and "M \<noteq> {}" and "finite N"
3100 shows "Max M \<le> Max N"
3103 interpret linorder "op \<ge>" "op >"
3104 by (rule dual_linorder)
3105 from assms show ?thesis
3106 by (simp add: Max fold1_antimono [folded dual_max])
3109 lemma finite_linorder_induct[consumes 1, case_names empty insert]:
3110 "finite A \<Longrightarrow> P {} \<Longrightarrow>
3111 (!!A b. finite A \<Longrightarrow> ALL a:A. a < b \<Longrightarrow> P A \<Longrightarrow> P(insert b A))
3112 \<Longrightarrow> P A"
3113 proof (induct A rule: measure_induct_rule[where f=card])
3115 assume IH: "!! B. card B < card A \<Longrightarrow> finite B \<Longrightarrow> P {} \<Longrightarrow>
3116 (!!A b. finite A \<Longrightarrow> (\<forall>a\<in>A. a<b) \<Longrightarrow> P A \<Longrightarrow> P (insert b A))
3117 \<Longrightarrow> P B"
3118 and "finite A" and "P {}"
3119 and step: "!!A b. \<lbrakk>finite A; \<forall>a\<in>A. a < b; P A\<rbrakk> \<Longrightarrow> P (insert b A)"
3121 proof (cases "A = {}")
3122 assume "A = {}" thus "P A" using `P {}` by simp
3124 let ?B = "A - {Max A}" let ?A = "insert (Max A) ?B"
3125 assume "A \<noteq> {}"
3126 with `finite A` have "Max A : A" by auto
3127 hence A: "?A = A" using insert_Diff_single insert_absorb by auto
3128 note card_Diff1_less[OF `finite A` `Max A : A`]
3129 moreover have "finite ?B" using `finite A` by simp
3130 ultimately have "P ?B" using `P {}` step IH by blast
3131 moreover have "\<forall>a\<in>?B. a < Max A"
3132 using Max_ge [OF `finite A`] by fastsimp
3133 ultimately show "P A"
3134 using A insert_Diff_single step[OF `finite ?B`] by fastsimp
3140 context ordered_ab_semigroup_add
3143 lemma add_Min_commute:
3145 assumes "finite N" and "N \<noteq> {}"
3146 shows "k + Min N = Min {k + m | m. m \<in> N}"
3148 have "\<And>x y. k + min x y = min (k + x) (k + y)"
3149 by (simp add: min_def not_le)
3150 (blast intro: antisym less_imp_le add_left_mono)
3151 with assms show ?thesis
3152 using hom_Min_commute [of "plus k" N]
3153 by simp (blast intro: arg_cong [where f = Min])
3156 lemma add_Max_commute:
3158 assumes "finite N" and "N \<noteq> {}"
3159 shows "k + Max N = Max {k + m | m. m \<in> N}"
3161 have "\<And>x y. k + max x y = max (k + x) (k + y)"
3162 by (simp add: max_def not_le)
3163 (blast intro: antisym less_imp_le add_left_mono)
3164 with assms show ?thesis
3165 using hom_Max_commute [of "plus k" N]
3166 by simp (blast intro: arg_cong [where f = Max])