| author | paulson | 
| Fri, 24 Jan 2003 18:13:59 +0100 | |
| changeset 13786 | ab8f39f48a6f | 
| parent 13737 | e564c3d2d174 | 
| child 13825 | ef4c41e7956a | 
| permissions | -rw-r--r-- | 
| 12396 | 1 | (* Title: HOL/Finite_Set.thy | 
| 2 | ID: $Id$ | |
| 3 | Author: Tobias Nipkow, Lawrence C Paulson and Markus Wenzel | |
| 4 | License: GPL (GNU GENERAL PUBLIC LICENSE) | |
| 5 | *) | |
| 6 | ||
| 7 | header {* Finite sets *}
 | |
| 8 | ||
| 9 | theory Finite_Set = Divides + Power + Inductive + SetInterval: | |
| 10 | ||
| 11 | subsection {* Collection of finite sets *}
 | |
| 12 | ||
| 13 | consts Finites :: "'a set set" | |
| 13737 | 14 | syntax | 
| 15 | finite :: "'a set => bool" | |
| 16 | translations | |
| 17 | "finite A" == "A : Finites" | |
| 12396 | 18 | |
| 19 | inductive Finites | |
| 20 | intros | |
| 21 |     emptyI [simp, intro!]: "{} : Finites"
 | |
| 22 | insertI [simp, intro!]: "A : Finites ==> insert a A : Finites" | |
| 23 | ||
| 24 | axclass finite \<subseteq> type | |
| 25 | finite: "finite UNIV" | |
| 26 | ||
| 13737 | 27 | lemma ex_new_if_finite: -- "does not depend on def of finite at all" | 
| 28 | "\<lbrakk> ~finite(UNIV::'a set); finite A \<rbrakk> \<Longrightarrow> \<exists>a::'a. a ~: A" | |
| 29 | by(subgoal_tac "A ~= UNIV", blast, blast) | |
| 30 | ||
| 12396 | 31 | |
| 32 | lemma finite_induct [case_names empty insert, induct set: Finites]: | |
| 33 | "finite F ==> | |
| 34 |     P {} ==> (!!F x. finite F ==> x \<notin> F ==> P F ==> P (insert x F)) ==> P F"
 | |
| 35 |   -- {* Discharging @{text "x \<notin> F"} entails extra work. *}
 | |
| 36 | proof - | |
| 13421 | 37 |   assume "P {}" and
 | 
| 38 | insert: "!!F x. finite F ==> x \<notin> F ==> P F ==> P (insert x F)" | |
| 12396 | 39 | assume "finite F" | 
| 40 | thus "P F" | |
| 41 | proof induct | |
| 42 |     show "P {}" .
 | |
| 43 | fix F x assume F: "finite F" and P: "P F" | |
| 44 | show "P (insert x F)" | |
| 45 | proof cases | |
| 46 | assume "x \<in> F" | |
| 47 | hence "insert x F = F" by (rule insert_absorb) | |
| 48 | with P show ?thesis by (simp only:) | |
| 49 | next | |
| 50 | assume "x \<notin> F" | |
| 51 | from F this P show ?thesis by (rule insert) | |
| 52 | qed | |
| 53 | qed | |
| 54 | qed | |
| 55 | ||
| 56 | lemma finite_subset_induct [consumes 2, case_names empty insert]: | |
| 57 | "finite F ==> F \<subseteq> A ==> | |
| 58 |     P {} ==> (!!F a. finite F ==> a \<in> A ==> a \<notin> F ==> P F ==> P (insert a F)) ==>
 | |
| 59 | P F" | |
| 60 | proof - | |
| 13421 | 61 |   assume "P {}" and insert:
 | 
| 62 | "!!F a. finite F ==> a \<in> A ==> a \<notin> F ==> P F ==> P (insert a F)" | |
| 12396 | 63 | assume "finite F" | 
| 64 | thus "F \<subseteq> A ==> P F" | |
| 65 | proof induct | |
| 66 |     show "P {}" .
 | |
| 67 | fix F x assume "finite F" and "x \<notin> F" | |
| 68 | and P: "F \<subseteq> A ==> P F" and i: "insert x F \<subseteq> A" | |
| 69 | show "P (insert x F)" | |
| 70 | proof (rule insert) | |
| 71 | from i show "x \<in> A" by blast | |
| 72 | from i have "F \<subseteq> A" by blast | |
| 73 | with P show "P F" . | |
| 74 | qed | |
| 75 | qed | |
| 76 | qed | |
| 77 | ||
| 78 | lemma finite_UnI: "finite F ==> finite G ==> finite (F Un G)" | |
| 79 |   -- {* The union of two finite sets is finite. *}
 | |
| 80 | by (induct set: Finites) simp_all | |
| 81 | ||
| 82 | lemma finite_subset: "A \<subseteq> B ==> finite B ==> finite A" | |
| 83 |   -- {* Every subset of a finite set is finite. *}
 | |
| 84 | proof - | |
| 85 | assume "finite B" | |
| 86 | thus "!!A. A \<subseteq> B ==> finite A" | |
| 87 | proof induct | |
| 88 | case empty | |
| 89 | thus ?case by simp | |
| 90 | next | |
| 91 | case (insert F x A) | |
| 92 |     have A: "A \<subseteq> insert x F" and r: "A - {x} \<subseteq> F ==> finite (A - {x})" .
 | |
| 93 | show "finite A" | |
| 94 | proof cases | |
| 95 | assume x: "x \<in> A" | |
| 96 |       with A have "A - {x} \<subseteq> F" by (simp add: subset_insert_iff)
 | |
| 97 |       with r have "finite (A - {x})" .
 | |
| 98 |       hence "finite (insert x (A - {x}))" ..
 | |
| 99 |       also have "insert x (A - {x}) = A" by (rule insert_Diff)
 | |
| 100 | finally show ?thesis . | |
| 101 | next | |
| 102 | show "A \<subseteq> F ==> ?thesis" . | |
| 103 | assume "x \<notin> A" | |
| 104 | with A show "A \<subseteq> F" by (simp add: subset_insert_iff) | |
| 105 | qed | |
| 106 | qed | |
| 107 | qed | |
| 108 | ||
| 109 | lemma finite_Un [iff]: "finite (F Un G) = (finite F & finite G)" | |
| 110 | by (blast intro: finite_subset [of _ "X Un Y", standard] finite_UnI) | |
| 111 | ||
| 112 | lemma finite_Int [simp, intro]: "finite F | finite G ==> finite (F Int G)" | |
| 113 |   -- {* The converse obviously fails. *}
 | |
| 114 | by (blast intro: finite_subset) | |
| 115 | ||
| 116 | lemma finite_insert [simp]: "finite (insert a A) = finite A" | |
| 117 | apply (subst insert_is_Un) | |
| 118 | apply (simp only: finite_Un) | |
| 119 | apply blast | |
| 120 | done | |
| 121 | ||
| 13490 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 122 | lemma finite_imageI[simp]: "finite F ==> finite (h ` F)" | 
| 12396 | 123 |   -- {* The image of a finite set is finite. *}
 | 
| 124 | by (induct set: Finites) simp_all | |
| 125 | ||
| 126 | lemma finite_range_imageI: | |
| 127 | "finite (range g) ==> finite (range (%x. f (g x)))" | |
| 128 | apply (drule finite_imageI) | |
| 129 | apply simp | |
| 130 | done | |
| 131 | ||
| 132 | lemma finite_empty_induct: | |
| 133 | "finite A ==> | |
| 134 |   P A ==> (!!a A. finite A ==> a:A ==> P A ==> P (A - {a})) ==> P {}"
 | |
| 135 | proof - | |
| 136 | assume "finite A" | |
| 137 |     and "P A" and "!!a A. finite A ==> a:A ==> P A ==> P (A - {a})"
 | |
| 138 | have "P (A - A)" | |
| 139 | proof - | |
| 140 | fix c b :: "'a set" | |
| 141 | presume c: "finite c" and b: "finite b" | |
| 142 |       and P1: "P b" and P2: "!!x y. finite y ==> x \<in> y ==> P y ==> P (y - {x})"
 | |
| 143 | from c show "c \<subseteq> b ==> P (b - c)" | |
| 144 | proof induct | |
| 145 | case empty | |
| 146 | from P1 show ?case by simp | |
| 147 | next | |
| 148 | case (insert F x) | |
| 149 |       have "P (b - F - {x})"
 | |
| 150 | proof (rule P2) | |
| 151 | from _ b show "finite (b - F)" by (rule finite_subset) blast | |
| 152 | from insert show "x \<in> b - F" by simp | |
| 153 | from insert show "P (b - F)" by simp | |
| 154 | qed | |
| 155 |       also have "b - F - {x} = b - insert x F" by (rule Diff_insert [symmetric])
 | |
| 156 | finally show ?case . | |
| 157 | qed | |
| 158 | next | |
| 159 | show "A \<subseteq> A" .. | |
| 160 | qed | |
| 161 |   thus "P {}" by simp
 | |
| 162 | qed | |
| 163 | ||
| 164 | lemma finite_Diff [simp]: "finite B ==> finite (B - Ba)" | |
| 165 | by (rule Diff_subset [THEN finite_subset]) | |
| 166 | ||
| 167 | lemma finite_Diff_insert [iff]: "finite (A - insert a B) = finite (A - B)" | |
| 168 | apply (subst Diff_insert) | |
| 169 | apply (case_tac "a : A - B") | |
| 170 | apply (rule finite_insert [symmetric, THEN trans]) | |
| 171 | apply (subst insert_Diff) | |
| 172 | apply simp_all | |
| 173 | done | |
| 174 | ||
| 175 | ||
| 176 | lemma finite_imageD: "finite (f`A) ==> inj_on f A ==> finite A" | |
| 177 | proof - | |
| 178 |   have aux: "!!A. finite (A - {}) = finite A" by simp
 | |
| 179 | fix B :: "'a set" | |
| 180 | assume "finite B" | |
| 181 | thus "!!A. f`A = B ==> inj_on f A ==> finite A" | |
| 182 | apply induct | |
| 183 | apply simp | |
| 184 |     apply (subgoal_tac "EX y:A. f y = x & F = f ` (A - {y})")
 | |
| 185 | apply clarify | |
| 186 | apply (simp (no_asm_use) add: inj_on_def) | |
| 187 | apply (blast dest!: aux [THEN iffD1]) | |
| 188 | apply atomize | |
| 189 | apply (erule_tac V = "ALL A. ?PP (A)" in thin_rl) | |
| 190 | apply (frule subsetD [OF equalityD2 insertI1]) | |
| 191 | apply clarify | |
| 192 | apply (rule_tac x = xa in bexI) | |
| 193 | apply (simp_all add: inj_on_image_set_diff) | |
| 194 | done | |
| 195 | qed (rule refl) | |
| 196 | ||
| 197 | ||
| 198 | subsubsection {* The finite UNION of finite sets *}
 | |
| 199 | ||
| 200 | lemma finite_UN_I: "finite A ==> (!!a. a:A ==> finite (B a)) ==> finite (UN a:A. B a)" | |
| 201 | by (induct set: Finites) simp_all | |
| 202 | ||
| 203 | text {*
 | |
| 204 | Strengthen RHS to | |
| 205 |   @{prop "((ALL x:A. finite (B x)) & finite {x. x:A & B x ~= {}})"}?
 | |
| 206 | ||
| 207 | We'd need to prove | |
| 208 |   @{prop "finite C ==> ALL A B. (UNION A B) <= C --> finite {x. x:A & B x ~= {}}"}
 | |
| 209 | by induction. *} | |
| 210 | ||
| 211 | lemma finite_UN [simp]: "finite A ==> finite (UNION A B) = (ALL x:A. finite (B x))" | |
| 212 | by (blast intro: finite_UN_I finite_subset) | |
| 213 | ||
| 214 | ||
| 215 | subsubsection {* Sigma of finite sets *}
 | |
| 216 | ||
| 217 | lemma finite_SigmaI [simp]: | |
| 218 | "finite A ==> (!!a. a:A ==> finite (B a)) ==> finite (SIGMA a:A. B a)" | |
| 219 | by (unfold Sigma_def) (blast intro!: finite_UN_I) | |
| 220 | ||
| 221 | lemma finite_Prod_UNIV: | |
| 222 |     "finite (UNIV::'a set) ==> finite (UNIV::'b set) ==> finite (UNIV::('a * 'b) set)"
 | |
| 223 |   apply (subgoal_tac "(UNIV:: ('a * 'b) set) = Sigma UNIV (%x. UNIV)")
 | |
| 224 | apply (erule ssubst) | |
| 225 | apply (erule finite_SigmaI) | |
| 226 | apply auto | |
| 227 | done | |
| 228 | ||
| 229 | instance unit :: finite | |
| 230 | proof | |
| 231 |   have "finite {()}" by simp
 | |
| 232 |   also have "{()} = UNIV" by auto
 | |
| 233 | finally show "finite (UNIV :: unit set)" . | |
| 234 | qed | |
| 235 | ||
| 236 | instance * :: (finite, finite) finite | |
| 237 | proof | |
| 238 |   show "finite (UNIV :: ('a \<times> 'b) set)"
 | |
| 239 | proof (rule finite_Prod_UNIV) | |
| 240 | show "finite (UNIV :: 'a set)" by (rule finite) | |
| 241 | show "finite (UNIV :: 'b set)" by (rule finite) | |
| 242 | qed | |
| 243 | qed | |
| 244 | ||
| 245 | ||
| 246 | subsubsection {* The powerset of a finite set *}
 | |
| 247 | ||
| 248 | lemma finite_Pow_iff [iff]: "finite (Pow A) = finite A" | |
| 249 | proof | |
| 250 | assume "finite (Pow A)" | |
| 251 |   with _ have "finite ((%x. {x}) ` A)" by (rule finite_subset) blast
 | |
| 252 | thus "finite A" by (rule finite_imageD [unfolded inj_on_def]) simp | |
| 253 | next | |
| 254 | assume "finite A" | |
| 255 | thus "finite (Pow A)" | |
| 256 | by induct (simp_all add: finite_UnI finite_imageI Pow_insert) | |
| 257 | qed | |
| 258 | ||
| 259 | lemma finite_converse [iff]: "finite (r^-1) = finite r" | |
| 260 | apply (subgoal_tac "r^-1 = (%(x,y). (y,x))`r") | |
| 261 | apply simp | |
| 262 | apply (rule iffI) | |
| 263 | apply (erule finite_imageD [unfolded inj_on_def]) | |
| 264 | apply (simp split add: split_split) | |
| 265 | apply (erule finite_imageI) | |
| 266 | apply (simp add: converse_def image_def) | |
| 267 | apply auto | |
| 268 | apply (rule bexI) | |
| 269 | prefer 2 apply assumption | |
| 270 | apply simp | |
| 271 | done | |
| 272 | ||
| 12937 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 273 | lemma finite_lessThan [iff]: fixes k :: nat shows "finite {..k(}"
 | 
| 12396 | 274 | by (induct k) (simp_all add: lessThan_Suc) | 
| 275 | ||
| 12937 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 276 | lemma finite_atMost [iff]: fixes k :: nat shows "finite {..k}"
 | 
| 12396 | 277 | by (induct k) (simp_all add: atMost_Suc) | 
| 278 | ||
| 13735 | 279 | lemma finite_greaterThanLessThan [iff]: | 
| 280 |   fixes l :: nat shows "finite {)l..u(}"
 | |
| 281 | by (simp add: greaterThanLessThan_def) | |
| 282 | ||
| 283 | lemma finite_atLeastLessThan [iff]: | |
| 284 |   fixes l :: nat shows "finite {l..u(}"
 | |
| 285 | by (simp add: atLeastLessThan_def) | |
| 286 | ||
| 287 | lemma finite_greaterThanAtMost [iff]: | |
| 288 |   fixes l :: nat shows "finite {)l..u}"
 | |
| 289 | by (simp add: greaterThanAtMost_def) | |
| 290 | ||
| 291 | lemma finite_atLeastAtMost [iff]: | |
| 292 |   fixes l :: nat shows "finite {l..u}"
 | |
| 293 | by (simp add: atLeastAtMost_def) | |
| 294 | ||
| 12396 | 295 | lemma bounded_nat_set_is_finite: | 
| 296 | "(ALL i:N. i < (n::nat)) ==> finite N" | |
| 297 |   -- {* A bounded set of natural numbers is finite. *}
 | |
| 298 | apply (rule finite_subset) | |
| 299 | apply (rule_tac [2] finite_lessThan) | |
| 300 | apply auto | |
| 301 | done | |
| 302 | ||
| 303 | ||
| 304 | subsubsection {* Finiteness of transitive closure *}
 | |
| 305 | ||
| 306 | text {* (Thanks to Sidi Ehmety) *}
 | |
| 307 | ||
| 308 | lemma finite_Field: "finite r ==> finite (Field r)" | |
| 309 |   -- {* A finite relation has a finite field (@{text "= domain \<union> range"}. *}
 | |
| 310 | apply (induct set: Finites) | |
| 311 | apply (auto simp add: Field_def Domain_insert Range_insert) | |
| 312 | done | |
| 313 | ||
| 314 | lemma trancl_subset_Field2: "r^+ <= Field r \<times> Field r" | |
| 315 | apply clarify | |
| 316 | apply (erule trancl_induct) | |
| 317 | apply (auto simp add: Field_def) | |
| 318 | done | |
| 319 | ||
| 320 | lemma finite_trancl: "finite (r^+) = finite r" | |
| 321 | apply auto | |
| 322 | prefer 2 | |
| 323 | apply (rule trancl_subset_Field2 [THEN finite_subset]) | |
| 324 | apply (rule finite_SigmaI) | |
| 325 | prefer 3 | |
| 13704 
854501b1e957
Transitive closure is now defined inductively as well.
 berghofe parents: 
13595diff
changeset | 326 | apply (blast intro: r_into_trancl' finite_subset) | 
| 12396 | 327 | apply (auto simp add: finite_Field) | 
| 328 | done | |
| 329 | ||
| 330 | ||
| 331 | subsection {* Finite cardinality *}
 | |
| 332 | ||
| 333 | text {*
 | |
| 334 |   This definition, although traditional, is ugly to work with: @{text
 | |
| 335 |   "card A == LEAST n. EX f. A = {f i | i. i < n}"}.  Therefore we have
 | |
| 336 | switched to an inductive one: | |
| 337 | *} | |
| 338 | ||
| 339 | consts cardR :: "('a set \<times> nat) set"
 | |
| 340 | ||
| 341 | inductive cardR | |
| 342 | intros | |
| 343 |     EmptyI: "({}, 0) : cardR"
 | |
| 344 | InsertI: "(A, n) : cardR ==> a \<notin> A ==> (insert a A, Suc n) : cardR" | |
| 345 | ||
| 346 | constdefs | |
| 347 | card :: "'a set => nat" | |
| 348 | "card A == THE n. (A, n) : cardR" | |
| 349 | ||
| 350 | inductive_cases cardR_emptyE: "({}, n) : cardR"
 | |
| 351 | inductive_cases cardR_insertE: "(insert a A,n) : cardR" | |
| 352 | ||
| 353 | lemma cardR_SucD: "(A, n) : cardR ==> a : A --> (EX m. n = Suc m)" | |
| 354 | by (induct set: cardR) simp_all | |
| 355 | ||
| 356 | lemma cardR_determ_aux1: | |
| 357 |     "(A, m): cardR ==> (!!n a. m = Suc n ==> a:A ==> (A - {a}, n) : cardR)"
 | |
| 358 | apply (induct set: cardR) | |
| 359 | apply auto | |
| 360 | apply (simp add: insert_Diff_if) | |
| 361 | apply auto | |
| 362 | apply (drule cardR_SucD) | |
| 363 | apply (blast intro!: cardR.intros) | |
| 364 | done | |
| 365 | ||
| 366 | lemma cardR_determ_aux2: "(insert a A, Suc m) : cardR ==> a \<notin> A ==> (A, m) : cardR" | |
| 367 | by (drule cardR_determ_aux1) auto | |
| 368 | ||
| 369 | lemma cardR_determ: "(A, m): cardR ==> (!!n. (A, n) : cardR ==> n = m)" | |
| 370 | apply (induct set: cardR) | |
| 371 | apply (safe elim!: cardR_emptyE cardR_insertE) | |
| 372 | apply (rename_tac B b m) | |
| 373 | apply (case_tac "a = b") | |
| 374 | apply (subgoal_tac "A = B") | |
| 375 | prefer 2 apply (blast elim: equalityE) | |
| 376 | apply blast | |
| 377 | apply (subgoal_tac "EX C. A = insert b C & B = insert a C") | |
| 378 | prefer 2 | |
| 379 | apply (rule_tac x = "A Int B" in exI) | |
| 380 | apply (blast elim: equalityE) | |
| 381 | apply (frule_tac A = B in cardR_SucD) | |
| 382 | apply (blast intro!: cardR.intros dest!: cardR_determ_aux2) | |
| 383 | done | |
| 384 | ||
| 385 | lemma cardR_imp_finite: "(A, n) : cardR ==> finite A" | |
| 386 | by (induct set: cardR) simp_all | |
| 387 | ||
| 388 | lemma finite_imp_cardR: "finite A ==> EX n. (A, n) : cardR" | |
| 389 | by (induct set: Finites) (auto intro!: cardR.intros) | |
| 390 | ||
| 391 | lemma card_equality: "(A,n) : cardR ==> card A = n" | |
| 392 | by (unfold card_def) (blast intro: cardR_determ) | |
| 393 | ||
| 394 | lemma card_empty [simp]: "card {} = 0"
 | |
| 395 | by (unfold card_def) (blast intro!: cardR.intros elim!: cardR_emptyE) | |
| 396 | ||
| 397 | lemma card_insert_disjoint [simp]: | |
| 398 | "finite A ==> x \<notin> A ==> card (insert x A) = Suc(card A)" | |
| 399 | proof - | |
| 400 | assume x: "x \<notin> A" | |
| 401 | hence aux: "!!n. ((insert x A, n) : cardR) = (EX m. (A, m) : cardR & n = Suc m)" | |
| 402 | apply (auto intro!: cardR.intros) | |
| 403 | apply (rule_tac A1 = A in finite_imp_cardR [THEN exE]) | |
| 404 | apply (force dest: cardR_imp_finite) | |
| 405 | apply (blast intro!: cardR.intros intro: cardR_determ) | |
| 406 | done | |
| 407 | assume "finite A" | |
| 408 | thus ?thesis | |
| 409 | apply (simp add: card_def aux) | |
| 410 | apply (rule the_equality) | |
| 411 | apply (auto intro: finite_imp_cardR | |
| 412 | cong: conj_cong simp: card_def [symmetric] card_equality) | |
| 413 | done | |
| 414 | qed | |
| 415 | ||
| 416 | lemma card_0_eq [simp]: "finite A ==> (card A = 0) = (A = {})"
 | |
| 417 | apply auto | |
| 418 | apply (drule_tac a = x in mk_disjoint_insert) | |
| 419 | apply clarify | |
| 420 | apply (rotate_tac -1) | |
| 421 | apply auto | |
| 422 | done | |
| 423 | ||
| 424 | lemma card_insert_if: | |
| 425 | "finite A ==> card (insert x A) = (if x:A then card A else Suc(card(A)))" | |
| 426 | by (simp add: insert_absorb) | |
| 427 | ||
| 428 | lemma card_Suc_Diff1: "finite A ==> x: A ==> Suc (card (A - {x})) = card A"
 | |
| 429 | apply (rule_tac t = A in insert_Diff [THEN subst]) | |
| 430 | apply assumption | |
| 431 | apply simp | |
| 432 | done | |
| 433 | ||
| 434 | lemma card_Diff_singleton: | |
| 435 |     "finite A ==> x: A ==> card (A - {x}) = card A - 1"
 | |
| 436 | by (simp add: card_Suc_Diff1 [symmetric]) | |
| 437 | ||
| 438 | lemma card_Diff_singleton_if: | |
| 439 |     "finite A ==> card (A-{x}) = (if x : A then card A - 1 else card A)"
 | |
| 440 | by (simp add: card_Diff_singleton) | |
| 441 | ||
| 442 | lemma card_insert: "finite A ==> card (insert x A) = Suc (card (A - {x}))"
 | |
| 443 | by (simp add: card_insert_if card_Suc_Diff1) | |
| 444 | ||
| 445 | lemma card_insert_le: "finite A ==> card A <= card (insert x A)" | |
| 446 | by (simp add: card_insert_if) | |
| 447 | ||
| 448 | lemma card_seteq: "finite B ==> (!!A. A <= B ==> card B <= card A ==> A = B)" | |
| 449 | apply (induct set: Finites) | |
| 450 | apply simp | |
| 451 | apply clarify | |
| 452 |   apply (subgoal_tac "finite A & A - {x} <= F")
 | |
| 453 | prefer 2 apply (blast intro: finite_subset) | |
| 454 | apply atomize | |
| 455 |   apply (drule_tac x = "A - {x}" in spec)
 | |
| 456 | apply (simp add: card_Diff_singleton_if split add: split_if_asm) | |
| 457 | apply (case_tac "card A") | |
| 458 | apply auto | |
| 459 | done | |
| 460 | ||
| 461 | lemma psubset_card_mono: "finite B ==> A < B ==> card A < card B" | |
| 462 | apply (simp add: psubset_def linorder_not_le [symmetric]) | |
| 463 | apply (blast dest: card_seteq) | |
| 464 | done | |
| 465 | ||
| 466 | lemma card_mono: "finite B ==> A <= B ==> card A <= card B" | |
| 467 | apply (case_tac "A = B") | |
| 468 | apply simp | |
| 469 | apply (simp add: linorder_not_less [symmetric]) | |
| 470 | apply (blast dest: card_seteq intro: order_less_imp_le) | |
| 471 | done | |
| 472 | ||
| 473 | lemma card_Un_Int: "finite A ==> finite B | |
| 474 | ==> card A + card B = card (A Un B) + card (A Int B)" | |
| 475 | apply (induct set: Finites) | |
| 476 | apply simp | |
| 477 | apply (simp add: insert_absorb Int_insert_left) | |
| 478 | done | |
| 479 | ||
| 480 | lemma card_Un_disjoint: "finite A ==> finite B | |
| 481 |     ==> A Int B = {} ==> card (A Un B) = card A + card B"
 | |
| 482 | by (simp add: card_Un_Int) | |
| 483 | ||
| 484 | lemma card_Diff_subset: | |
| 485 | "finite A ==> B <= A ==> card A - card B = card (A - B)" | |
| 486 | apply (subgoal_tac "(A - B) Un B = A") | |
| 487 | prefer 2 apply blast | |
| 488 | apply (rule add_right_cancel [THEN iffD1]) | |
| 489 | apply (rule card_Un_disjoint [THEN subst]) | |
| 490 | apply (erule_tac [4] ssubst) | |
| 491 | prefer 3 apply blast | |
| 492 | apply (simp_all add: add_commute not_less_iff_le | |
| 493 | add_diff_inverse card_mono finite_subset) | |
| 494 | done | |
| 495 | ||
| 496 | lemma card_Diff1_less: "finite A ==> x: A ==> card (A - {x}) < card A"
 | |
| 497 | apply (rule Suc_less_SucD) | |
| 498 | apply (simp add: card_Suc_Diff1) | |
| 499 | done | |
| 500 | ||
| 501 | lemma card_Diff2_less: | |
| 502 |     "finite A ==> x: A ==> y: A ==> card (A - {x} - {y}) < card A"
 | |
| 503 | apply (case_tac "x = y") | |
| 504 | apply (simp add: card_Diff1_less) | |
| 505 | apply (rule less_trans) | |
| 506 | prefer 2 apply (auto intro!: card_Diff1_less) | |
| 507 | done | |
| 508 | ||
| 509 | lemma card_Diff1_le: "finite A ==> card (A - {x}) <= card A"
 | |
| 510 | apply (case_tac "x : A") | |
| 511 | apply (simp_all add: card_Diff1_less less_imp_le) | |
| 512 | done | |
| 513 | ||
| 514 | lemma card_psubset: "finite B ==> A \<subseteq> B ==> card A < card B ==> A < B" | |
| 515 | apply (erule psubsetI) | |
| 516 | apply blast | |
| 517 | done | |
| 518 | ||
| 519 | ||
| 520 | subsubsection {* Cardinality of image *}
 | |
| 521 | ||
| 522 | lemma card_image_le: "finite A ==> card (f ` A) <= card A" | |
| 523 | apply (induct set: Finites) | |
| 524 | apply simp | |
| 525 | apply (simp add: le_SucI finite_imageI card_insert_if) | |
| 526 | done | |
| 527 | ||
| 528 | lemma card_image: "finite A ==> inj_on f A ==> card (f ` A) = card A" | |
| 529 | apply (induct set: Finites) | |
| 530 | apply simp_all | |
| 531 | apply atomize | |
| 532 | apply safe | |
| 533 | apply (unfold inj_on_def) | |
| 534 | apply blast | |
| 535 | apply (subst card_insert_disjoint) | |
| 536 | apply (erule finite_imageI) | |
| 537 | apply blast | |
| 538 | apply blast | |
| 539 | done | |
| 540 | ||
| 541 | lemma endo_inj_surj: "finite A ==> f ` A \<subseteq> A ==> inj_on f A ==> f ` A = A" | |
| 542 | by (simp add: card_seteq card_image) | |
| 543 | ||
| 544 | ||
| 545 | subsubsection {* Cardinality of the Powerset *}
 | |
| 546 | ||
| 547 | lemma card_Pow: "finite A ==> card (Pow A) = Suc (Suc 0) ^ card A" (* FIXME numeral 2 (!?) *) | |
| 548 | apply (induct set: Finites) | |
| 549 | apply (simp_all add: Pow_insert) | |
| 550 | apply (subst card_Un_disjoint) | |
| 551 | apply blast | |
| 552 | apply (blast intro: finite_imageI) | |
| 553 | apply blast | |
| 554 | apply (subgoal_tac "inj_on (insert x) (Pow F)") | |
| 555 | apply (simp add: card_image Pow_insert) | |
| 556 | apply (unfold inj_on_def) | |
| 557 | apply (blast elim!: equalityE) | |
| 558 | done | |
| 559 | ||
| 560 | text {*
 | |
| 561 | \medskip Relates to equivalence classes. Based on a theorem of | |
| 562 |   F. Kammüller's.  The @{prop "finite C"} premise is redundant.
 | |
| 563 | *} | |
| 564 | ||
| 565 | lemma dvd_partition: | |
| 566 | "finite C ==> finite (Union C) ==> | |
| 567 | ALL c : C. k dvd card c ==> | |
| 568 |     (ALL c1: C. ALL c2: C. c1 ~= c2 --> c1 Int c2 = {}) ==>
 | |
| 569 | k dvd card (Union C)" | |
| 570 | apply (induct set: Finites) | |
| 571 | apply simp_all | |
| 572 | apply clarify | |
| 573 | apply (subst card_Un_disjoint) | |
| 574 | apply (auto simp add: dvd_add disjoint_eq_subset_Compl) | |
| 575 | done | |
| 576 | ||
| 577 | ||
| 578 | subsection {* A fold functional for finite sets *}
 | |
| 579 | ||
| 580 | text {*
 | |
| 581 |   For @{text n} non-negative we have @{text "fold f e {x1, ..., xn} =
 | |
| 582 |   f x1 (... (f xn e))"} where @{text f} is at least left-commutative.
 | |
| 583 | *} | |
| 584 | ||
| 585 | consts | |
| 586 |   foldSet :: "('b => 'a => 'a) => 'a => ('b set \<times> 'a) set"
 | |
| 587 | ||
| 588 | inductive "foldSet f e" | |
| 589 | intros | |
| 590 |     emptyI [intro]: "({}, e) : foldSet f e"
 | |
| 591 | insertI [intro]: "x \<notin> A ==> (A, y) : foldSet f e ==> (insert x A, f x y) : foldSet f e" | |
| 592 | ||
| 593 | inductive_cases empty_foldSetE [elim!]: "({}, x) : foldSet f e"
 | |
| 594 | ||
| 595 | constdefs | |
| 596 |   fold :: "('b => 'a => 'a) => 'a => 'b set => 'a"
 | |
| 597 | "fold f e A == THE x. (A, x) : foldSet f e" | |
| 598 | ||
| 599 | lemma Diff1_foldSet: "(A - {x}, y) : foldSet f e ==> x: A ==> (A, f x y) : foldSet f e"
 | |
| 600 | apply (erule insert_Diff [THEN subst], rule foldSet.intros) | |
| 601 | apply auto | |
| 602 | done | |
| 603 | ||
| 604 | lemma foldSet_imp_finite [simp]: "(A, x) : foldSet f e ==> finite A" | |
| 605 | by (induct set: foldSet) auto | |
| 606 | ||
| 607 | lemma finite_imp_foldSet: "finite A ==> EX x. (A, x) : foldSet f e" | |
| 608 | by (induct set: Finites) auto | |
| 609 | ||
| 610 | ||
| 611 | subsubsection {* Left-commutative operations *}
 | |
| 612 | ||
| 613 | locale LC = | |
| 614 | fixes f :: "'b => 'a => 'a" (infixl "\<cdot>" 70) | |
| 615 | assumes left_commute: "x \<cdot> (y \<cdot> z) = y \<cdot> (x \<cdot> z)" | |
| 616 | ||
| 617 | lemma (in LC) foldSet_determ_aux: | |
| 618 | "ALL A x. card A < n --> (A, x) : foldSet f e --> | |
| 619 | (ALL y. (A, y) : foldSet f e --> y = x)" | |
| 620 | apply (induct n) | |
| 621 | apply (auto simp add: less_Suc_eq) | |
| 622 | apply (erule foldSet.cases) | |
| 623 | apply blast | |
| 624 | apply (erule foldSet.cases) | |
| 625 | apply blast | |
| 626 | apply clarify | |
| 627 |   txt {* force simplification of @{text "card A < card (insert ...)"}. *}
 | |
| 628 | apply (erule rev_mp) | |
| 629 | apply (simp add: less_Suc_eq_le) | |
| 630 | apply (rule impI) | |
| 631 | apply (rename_tac Aa xa ya Ab xb yb, case_tac "xa = xb") | |
| 632 | apply (subgoal_tac "Aa = Ab") | |
| 633 | prefer 2 apply (blast elim!: equalityE) | |
| 634 | apply blast | |
| 635 |   txt {* case @{prop "xa \<notin> xb"}. *}
 | |
| 636 |   apply (subgoal_tac "Aa - {xb} = Ab - {xa} & xb : Aa & xa : Ab")
 | |
| 637 | prefer 2 apply (blast elim!: equalityE) | |
| 638 | apply clarify | |
| 639 |   apply (subgoal_tac "Aa = insert xb Ab - {xa}")
 | |
| 640 | prefer 2 apply blast | |
| 641 | apply (subgoal_tac "card Aa <= card Ab") | |
| 642 | prefer 2 | |
| 643 | apply (rule Suc_le_mono [THEN subst]) | |
| 644 | apply (simp add: card_Suc_Diff1) | |
| 645 |   apply (rule_tac A1 = "Aa - {xb}" and f1 = f in finite_imp_foldSet [THEN exE])
 | |
| 646 | apply (blast intro: foldSet_imp_finite finite_Diff) | |
| 647 | apply (frule (1) Diff1_foldSet) | |
| 648 | apply (subgoal_tac "ya = f xb x") | |
| 649 | prefer 2 apply (blast del: equalityCE) | |
| 650 |   apply (subgoal_tac "(Ab - {xa}, x) : foldSet f e")
 | |
| 651 | prefer 2 apply simp | |
| 652 | apply (subgoal_tac "yb = f xa x") | |
| 653 | prefer 2 apply (blast del: equalityCE dest: Diff1_foldSet) | |
| 654 | apply (simp (no_asm_simp) add: left_commute) | |
| 655 | done | |
| 656 | ||
| 657 | lemma (in LC) foldSet_determ: "(A, x) : foldSet f e ==> (A, y) : foldSet f e ==> y = x" | |
| 658 | by (blast intro: foldSet_determ_aux [rule_format]) | |
| 659 | ||
| 660 | lemma (in LC) fold_equality: "(A, y) : foldSet f e ==> fold f e A = y" | |
| 661 | by (unfold fold_def) (blast intro: foldSet_determ) | |
| 662 | ||
| 663 | lemma fold_empty [simp]: "fold f e {} = e"
 | |
| 664 | by (unfold fold_def) blast | |
| 665 | ||
| 666 | lemma (in LC) fold_insert_aux: "x \<notin> A ==> | |
| 667 | ((insert x A, v) : foldSet f e) = | |
| 668 | (EX y. (A, y) : foldSet f e & v = f x y)" | |
| 669 | apply auto | |
| 670 | apply (rule_tac A1 = A and f1 = f in finite_imp_foldSet [THEN exE]) | |
| 671 | apply (fastsimp dest: foldSet_imp_finite) | |
| 672 | apply (blast intro: foldSet_determ) | |
| 673 | done | |
| 674 | ||
| 675 | lemma (in LC) fold_insert: | |
| 676 | "finite A ==> x \<notin> A ==> fold f e (insert x A) = f x (fold f e A)" | |
| 677 | apply (unfold fold_def) | |
| 678 | apply (simp add: fold_insert_aux) | |
| 679 | apply (rule the_equality) | |
| 680 | apply (auto intro: finite_imp_foldSet | |
| 681 | cong add: conj_cong simp add: fold_def [symmetric] fold_equality) | |
| 682 | done | |
| 683 | ||
| 684 | lemma (in LC) fold_commute: "finite A ==> (!!e. f x (fold f e A) = fold f (f x e) A)" | |
| 685 | apply (induct set: Finites) | |
| 686 | apply simp | |
| 687 | apply (simp add: left_commute fold_insert) | |
| 688 | done | |
| 689 | ||
| 690 | lemma (in LC) fold_nest_Un_Int: | |
| 691 | "finite A ==> finite B | |
| 692 | ==> fold f (fold f e B) A = fold f (fold f e (A Int B)) (A Un B)" | |
| 693 | apply (induct set: Finites) | |
| 694 | apply simp | |
| 695 | apply (simp add: fold_insert fold_commute Int_insert_left insert_absorb) | |
| 696 | done | |
| 697 | ||
| 698 | lemma (in LC) fold_nest_Un_disjoint: | |
| 699 |   "finite A ==> finite B ==> A Int B = {}
 | |
| 700 | ==> fold f e (A Un B) = fold f (fold f e B) A" | |
| 701 | by (simp add: fold_nest_Un_Int) | |
| 702 | ||
| 703 | declare foldSet_imp_finite [simp del] | |
| 704 | empty_foldSetE [rule del] foldSet.intros [rule del] | |
| 705 |   -- {* Delete rules to do with @{text foldSet} relation. *}
 | |
| 706 | ||
| 707 | ||
| 708 | ||
| 709 | subsubsection {* Commutative monoids *}
 | |
| 710 | ||
| 711 | text {*
 | |
| 712 |   We enter a more restrictive context, with @{text "f :: 'a => 'a => 'a"}
 | |
| 713 |   instead of @{text "'b => 'a => 'a"}.
 | |
| 714 | *} | |
| 715 | ||
| 716 | locale ACe = | |
| 717 | fixes f :: "'a => 'a => 'a" (infixl "\<cdot>" 70) | |
| 718 | and e :: 'a | |
| 719 | assumes ident [simp]: "x \<cdot> e = x" | |
| 720 | and commute: "x \<cdot> y = y \<cdot> x" | |
| 721 | and assoc: "(x \<cdot> y) \<cdot> z = x \<cdot> (y \<cdot> z)" | |
| 722 | ||
| 723 | lemma (in ACe) left_commute: "x \<cdot> (y \<cdot> z) = y \<cdot> (x \<cdot> z)" | |
| 724 | proof - | |
| 725 | have "x \<cdot> (y \<cdot> z) = (y \<cdot> z) \<cdot> x" by (simp only: commute) | |
| 726 | also have "... = y \<cdot> (z \<cdot> x)" by (simp only: assoc) | |
| 727 | also have "z \<cdot> x = x \<cdot> z" by (simp only: commute) | |
| 728 | finally show ?thesis . | |
| 729 | qed | |
| 730 | ||
| 12718 | 731 | lemmas (in ACe) AC = assoc commute left_commute | 
| 12396 | 732 | |
| 12693 | 733 | lemma (in ACe) left_ident [simp]: "e \<cdot> x = x" | 
| 12396 | 734 | proof - | 
| 735 | have "x \<cdot> e = x" by (rule ident) | |
| 736 | thus ?thesis by (subst commute) | |
| 737 | qed | |
| 738 | ||
| 739 | lemma (in ACe) fold_Un_Int: | |
| 740 | "finite A ==> finite B ==> | |
| 741 | fold f e A \<cdot> fold f e B = fold f e (A Un B) \<cdot> fold f e (A Int B)" | |
| 742 | apply (induct set: Finites) | |
| 743 | apply simp | |
| 13400 | 744 | apply (simp add: AC insert_absorb Int_insert_left | 
| 13421 | 745 | LC.fold_insert [OF LC.intro]) | 
| 12396 | 746 | done | 
| 747 | ||
| 748 | lemma (in ACe) fold_Un_disjoint: | |
| 749 |   "finite A ==> finite B ==> A Int B = {} ==>
 | |
| 750 | fold f e (A Un B) = fold f e A \<cdot> fold f e B" | |
| 751 | by (simp add: fold_Un_Int) | |
| 752 | ||
| 753 | lemma (in ACe) fold_Un_disjoint2: | |
| 754 |   "finite A ==> finite B ==> A Int B = {} ==>
 | |
| 755 | fold (f o g) e (A Un B) = fold (f o g) e A \<cdot> fold (f o g) e B" | |
| 756 | proof - | |
| 757 | assume b: "finite B" | |
| 758 | assume "finite A" | |
| 759 |   thus "A Int B = {} ==>
 | |
| 760 | fold (f o g) e (A Un B) = fold (f o g) e A \<cdot> fold (f o g) e B" | |
| 761 | proof induct | |
| 762 | case empty | |
| 763 | thus ?case by simp | |
| 764 | next | |
| 765 | case (insert F x) | |
| 13571 | 766 | have "fold (f o g) e (insert x F \<union> B) = fold (f o g) e (insert x (F \<union> B))" | 
| 12396 | 767 | by simp | 
| 13571 | 768 | also have "... = (f o g) x (fold (f o g) e (F \<union> B))" | 
| 13400 | 769 | by (rule LC.fold_insert [OF LC.intro]) | 
| 13421 | 770 | (insert b insert, auto simp add: left_commute) | 
| 13571 | 771 | also from insert have "fold (f o g) e (F \<union> B) = | 
| 772 | fold (f o g) e F \<cdot> fold (f o g) e B" by blast | |
| 773 | also have "(f o g) x ... = (f o g) x (fold (f o g) e F) \<cdot> fold (f o g) e B" | |
| 12396 | 774 | by (simp add: AC) | 
| 13571 | 775 | also have "(f o g) x (fold (f o g) e F) = fold (f o g) e (insert x F)" | 
| 13400 | 776 | by (rule LC.fold_insert [OF LC.intro, symmetric]) (insert b insert, | 
| 13421 | 777 | auto simp add: left_commute) | 
| 12396 | 778 | finally show ?case . | 
| 779 | qed | |
| 780 | qed | |
| 781 | ||
| 782 | ||
| 783 | subsection {* Generalized summation over a set *}
 | |
| 784 | ||
| 785 | constdefs | |
| 786 |   setsum :: "('a => 'b) => 'a set => 'b::plus_ac0"
 | |
| 787 | "setsum f A == if finite A then fold (op + o f) 0 A else 0" | |
| 788 | ||
| 789 | syntax | |
| 790 |   "_setsum" :: "idt => 'a set => 'b => 'b::plus_ac0"    ("\<Sum>_:_. _" [0, 51, 10] 10)
 | |
| 791 | syntax (xsymbols) | |
| 792 |   "_setsum" :: "idt => 'a set => 'b => 'b::plus_ac0"    ("\<Sum>_\<in>_. _" [0, 51, 10] 10)
 | |
| 793 | translations | |
| 794 |   "\<Sum>i:A. b" == "setsum (%i. b) A"  -- {* Beware of argument permutation! *}
 | |
| 795 | ||
| 796 | ||
| 797 | lemma setsum_empty [simp]: "setsum f {} = 0"
 | |
| 798 | by (simp add: setsum_def) | |
| 799 | ||
| 800 | lemma setsum_insert [simp]: | |
| 801 | "finite F ==> a \<notin> F ==> setsum f (insert a F) = f a + setsum f F" | |
| 13365 | 802 | by (simp add: setsum_def | 
| 13421 | 803 | LC.fold_insert [OF LC.intro] plus_ac0_left_commute) | 
| 12396 | 804 | |
| 805 | lemma setsum_0: "setsum (\<lambda>i. 0) A = 0" | |
| 806 | apply (case_tac "finite A") | |
| 807 | prefer 2 apply (simp add: setsum_def) | |
| 808 | apply (erule finite_induct) | |
| 809 | apply auto | |
| 810 | done | |
| 811 | ||
| 812 | lemma setsum_eq_0_iff [simp]: | |
| 813 | "finite F ==> (setsum f F = 0) = (ALL a:F. f a = (0::nat))" | |
| 814 | by (induct set: Finites) auto | |
| 815 | ||
| 816 | lemma setsum_SucD: "setsum f A = Suc n ==> EX a:A. 0 < f a" | |
| 817 | apply (case_tac "finite A") | |
| 818 | prefer 2 apply (simp add: setsum_def) | |
| 819 | apply (erule rev_mp) | |
| 820 | apply (erule finite_induct) | |
| 821 | apply auto | |
| 822 | done | |
| 823 | ||
| 824 | lemma card_eq_setsum: "finite A ==> card A = setsum (\<lambda>x. 1) A" | |
| 825 |   -- {* Could allow many @{text "card"} proofs to be simplified. *}
 | |
| 826 | by (induct set: Finites) auto | |
| 827 | ||
| 828 | lemma setsum_Un_Int: "finite A ==> finite B | |
| 829 | ==> setsum g (A Un B) + setsum g (A Int B) = setsum g A + setsum g B" | |
| 830 |   -- {* The reversed orientation looks more natural, but LOOPS as a simprule! *}
 | |
| 831 | apply (induct set: Finites) | |
| 832 | apply simp | |
| 833 | apply (simp add: plus_ac0 Int_insert_left insert_absorb) | |
| 834 | done | |
| 835 | ||
| 836 | lemma setsum_Un_disjoint: "finite A ==> finite B | |
| 837 |   ==> A Int B = {} ==> setsum g (A Un B) = setsum g A + setsum g B"
 | |
| 838 | apply (subst setsum_Un_Int [symmetric]) | |
| 839 | apply auto | |
| 840 | done | |
| 841 | ||
| 12937 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 842 | lemma setsum_UN_disjoint: | 
| 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 843 | fixes f :: "'a => 'b::plus_ac0" | 
| 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 844 | shows | 
| 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 845 | "finite I ==> (ALL i:I. finite (A i)) ==> | 
| 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 846 |         (ALL i:I. ALL j:I. i \<noteq> j --> A i Int A j = {}) ==>
 | 
| 
0c4fd7529467
clarified syntax of ``long'' statements: fixes/assumes/shows;
 wenzelm parents: 
12718diff
changeset | 847 | setsum f (UNION I A) = setsum (\<lambda>i. setsum f (A i)) I" | 
| 12396 | 848 | apply (induct set: Finites) | 
| 849 | apply simp | |
| 850 | apply atomize | |
| 851 | apply (subgoal_tac "ALL i:F. x \<noteq> i") | |
| 852 | prefer 2 apply blast | |
| 853 |   apply (subgoal_tac "A x Int UNION F A = {}")
 | |
| 854 | prefer 2 apply blast | |
| 855 | apply (simp add: setsum_Un_disjoint) | |
| 856 | done | |
| 857 | ||
| 858 | lemma setsum_addf: "setsum (\<lambda>x. f x + g x) A = (setsum f A + setsum g A)" | |
| 859 | apply (case_tac "finite A") | |
| 860 | prefer 2 apply (simp add: setsum_def) | |
| 861 | apply (erule finite_induct) | |
| 862 | apply auto | |
| 863 | apply (simp add: plus_ac0) | |
| 864 | done | |
| 865 | ||
| 866 | lemma setsum_Un: "finite A ==> finite B ==> | |
| 867 | (setsum f (A Un B) :: nat) = setsum f A + setsum f B - setsum f (A Int B)" | |
| 868 |   -- {* For the natural numbers, we have subtraction. *}
 | |
| 869 | apply (subst setsum_Un_Int [symmetric]) | |
| 870 | apply auto | |
| 871 | done | |
| 872 | ||
| 873 | lemma setsum_diff1: "(setsum f (A - {a}) :: nat) =
 | |
| 874 | (if a:A then setsum f A - f a else setsum f A)" | |
| 875 | apply (case_tac "finite A") | |
| 876 | prefer 2 apply (simp add: setsum_def) | |
| 877 | apply (erule finite_induct) | |
| 878 | apply (auto simp add: insert_Diff_if) | |
| 879 | apply (drule_tac a = a in mk_disjoint_insert) | |
| 880 | apply auto | |
| 881 | done | |
| 882 | ||
| 883 | lemma setsum_cong: | |
| 884 | "A = B ==> (!!x. x:B ==> f x = g x) ==> setsum f A = setsum g B" | |
| 885 | apply (case_tac "finite B") | |
| 886 | prefer 2 apply (simp add: setsum_def) | |
| 887 | apply simp | |
| 888 | apply (subgoal_tac "ALL C. C <= B --> (ALL x:C. f x = g x) --> setsum f C = setsum g C") | |
| 889 | apply simp | |
| 890 | apply (erule finite_induct) | |
| 891 | apply simp | |
| 892 | apply (simp add: subset_insert_iff) | |
| 893 | apply clarify | |
| 894 | apply (subgoal_tac "finite C") | |
| 895 | prefer 2 apply (blast dest: finite_subset [COMP swap_prems_rl]) | |
| 896 |   apply (subgoal_tac "C = insert x (C - {x})")
 | |
| 897 | prefer 2 apply blast | |
| 898 | apply (erule ssubst) | |
| 899 | apply (drule spec) | |
| 900 | apply (erule (1) notE impE) | |
| 901 | apply (simp add: Ball_def) | |
| 902 | done | |
| 903 | ||
| 13490 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 904 | subsubsection{* Min and Max of finite linearly ordered sets *}
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 905 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 906 | text{* Seemed easier to define directly than via fold. *}
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 907 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 908 | lemma ex_Max: fixes S :: "('a::linorder)set"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 909 |   assumes fin: "finite S" shows "S \<noteq> {} \<Longrightarrow> \<exists>m\<in>S. \<forall>s \<in> S. s \<le> m"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 910 | using fin | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 911 | proof (induct) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 912 | case empty thus ?case by simp | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 913 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 914 | case (insert S x) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 915 | show ?case | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 916 | proof (cases) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 917 |     assume "S = {}" thus ?thesis by simp
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 918 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 919 |     assume nonempty: "S \<noteq> {}"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 920 | then obtain m where m: "m\<in>S" "\<forall>s\<in>S. s \<le> m" using insert by blast | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 921 | show ?thesis | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 922 | proof (cases) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 923 | assume "x \<le> m" thus ?thesis using m by blast | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 924 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 925 | assume "\<not> x \<le> m" thus ?thesis using m | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 926 | by(simp add:linorder_not_le order_less_le)(blast intro: order_trans) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 927 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 928 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 929 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 930 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 931 | lemma ex_Min: fixes S :: "('a::linorder)set"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 932 |   assumes fin: "finite S" shows "S \<noteq> {} \<Longrightarrow> \<exists>m\<in>S. \<forall>s \<in> S. m \<le> s"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 933 | using fin | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 934 | proof (induct) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 935 | case empty thus ?case by simp | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 936 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 937 | case (insert S x) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 938 | show ?case | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 939 | proof (cases) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 940 |     assume "S = {}" thus ?thesis by simp
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 941 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 942 |     assume nonempty: "S \<noteq> {}"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 943 | then obtain m where m: "m\<in>S" "\<forall>s\<in>S. m \<le> s" using insert by blast | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 944 | show ?thesis | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 945 | proof (cases) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 946 | assume "m \<le> x" thus ?thesis using m by blast | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 947 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 948 | assume "\<not> m \<le> x" thus ?thesis using m | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 949 | by(simp add:linorder_not_le order_less_le)(blast intro: order_trans) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 950 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 951 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 952 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 953 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 954 | constdefs | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 955 |  Min :: "('a::linorder)set \<Rightarrow> 'a"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 956 | "Min S \<equiv> THE m. m \<in> S \<and> (\<forall>s \<in> S. m \<le> s)" | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 957 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 958 |  Max :: "('a::linorder)set \<Rightarrow> 'a"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 959 | "Max S \<equiv> THE m. m \<in> S \<and> (\<forall>s \<in> S. s \<le> m)" | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 960 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 961 | lemma Min[simp]: assumes a: "finite S" "S \<noteq> {}"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 962 | shows "Min S \<in> S \<and> (\<forall>s \<in> S. Min S \<le> s)" (is "?P(Min S)") | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 963 | proof (unfold Min_def, rule theI') | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 964 | show "\<exists>!m. ?P m" | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 965 | proof (rule ex_ex1I) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 966 | show "\<exists>m. ?P m" using ex_Min[OF a] by blast | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 967 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 968 | fix m1 m2 assume "?P m1" "?P m2" | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 969 | thus "m1 = m2" by (blast dest:order_antisym) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 970 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 971 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 972 | |
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 973 | lemma Max[simp]: assumes a: "finite S" "S \<noteq> {}"
 | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 974 | shows "Max S \<in> S \<and> (\<forall>s \<in> S. s \<le> Max S)" (is "?P(Max S)") | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 975 | proof (unfold Max_def, rule theI') | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 976 | show "\<exists>!m. ?P m" | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 977 | proof (rule ex_ex1I) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 978 | show "\<exists>m. ?P m" using ex_Max[OF a] by blast | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 979 | next | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 980 | fix m1 m2 assume "?P m1" "?P m2" | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 981 | thus "m1 = m2" by (blast dest:order_antisym) | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 982 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 983 | qed | 
| 
44bdc150211b
Added Mi and Max on sets, hid Min and Pls on numerals.
 nipkow parents: 
13421diff
changeset | 984 | |
| 12396 | 985 | |
| 986 | text {*
 | |
| 987 |   \medskip Basic theorem about @{text "choose"}.  By Florian
 | |
| 988 | Kammüller, tidied by LCP. | |
| 989 | *} | |
| 990 | ||
| 991 | lemma card_s_0_eq_empty: | |
| 992 |     "finite A ==> card {B. B \<subseteq> A & card B = 0} = 1"
 | |
| 993 | apply (simp cong add: conj_cong add: finite_subset [THEN card_0_eq]) | |
| 994 | apply (simp cong add: rev_conj_cong) | |
| 995 | done | |
| 996 | ||
| 997 | lemma choose_deconstruct: "finite M ==> x \<notin> M | |
| 998 |   ==> {s. s <= insert x M & card(s) = Suc k}
 | |
| 999 |        = {s. s <= M & card(s) = Suc k} Un
 | |
| 1000 |          {s. EX t. t <= M & card(t) = k & s = insert x t}"
 | |
| 1001 | apply safe | |
| 1002 | apply (auto intro: finite_subset [THEN card_insert_disjoint]) | |
| 1003 |   apply (drule_tac x = "xa - {x}" in spec)
 | |
| 1004 | apply (subgoal_tac "x ~: xa") | |
| 1005 | apply auto | |
| 1006 | apply (erule rev_mp, subst card_Diff_singleton) | |
| 1007 | apply (auto intro: finite_subset) | |
| 1008 | done | |
| 1009 | ||
| 1010 | lemma card_inj_on_le: | |
| 13595 | 1011 | "[|inj_on f A; f ` A \<subseteq> B; finite A; finite B |] ==> card A <= card B" | 
| 12396 | 1012 | by (auto intro: card_mono simp add: card_image [symmetric]) | 
| 1013 | ||
| 13595 | 1014 | lemma card_bij_eq: | 
| 1015 | "[|inj_on f A; f ` A \<subseteq> B; inj_on g B; g ` B \<subseteq> A; | |
| 1016 | finite A; finite B |] ==> card A = card B" | |
| 12396 | 1017 | by (auto intro: le_anti_sym card_inj_on_le) | 
| 1018 | ||
| 13595 | 1019 | text{*There are as many subsets of @{term A} having cardinality @{term k}
 | 
| 1020 | as there are sets obtained from the former by inserting a fixed element | |
| 1021 |  @{term x} into each.*}
 | |
| 1022 | lemma constr_bij: | |
| 1023 | "[|finite A; x \<notin> A|] ==> | |
| 1024 |     card {B. EX C. C <= A & card(C) = k & B = insert x C} =
 | |
| 12396 | 1025 |     card {B. B <= A & card(B) = k}"
 | 
| 1026 |   apply (rule_tac f = "%s. s - {x}" and g = "insert x" in card_bij_eq)
 | |
| 13595 | 1027 | apply (auto elim!: equalityE simp add: inj_on_def) | 
| 1028 | apply (subst Diff_insert0, auto) | |
| 1029 |    txt {* finiteness of the two sets *}
 | |
| 1030 | apply (rule_tac [2] B = "Pow (A)" in finite_subset) | |
| 1031 | apply (rule_tac B = "Pow (insert x A)" in finite_subset) | |
| 1032 | apply fast+ | |
| 12396 | 1033 | done | 
| 1034 | ||
| 1035 | text {*
 | |
| 1036 | Main theorem: combinatorial statement about number of subsets of a set. | |
| 1037 | *} | |
| 1038 | ||
| 1039 | lemma n_sub_lemma: | |
| 1040 |   "!!A. finite A ==> card {B. B <= A & card B = k} = (card A choose k)"
 | |
| 1041 | apply (induct k) | |
| 1042 | apply (simp add: card_s_0_eq_empty) | |
| 1043 | apply atomize | |
| 1044 | apply (rotate_tac -1, erule finite_induct) | |
| 13421 | 1045 | apply (simp_all (no_asm_simp) cong add: conj_cong | 
| 1046 | add: card_s_0_eq_empty choose_deconstruct) | |
| 12396 | 1047 | apply (subst card_Un_disjoint) | 
| 1048 | prefer 4 apply (force simp add: constr_bij) | |
| 1049 | prefer 3 apply force | |
| 1050 | prefer 2 apply (blast intro: finite_Pow_iff [THEN iffD2] | |
| 1051 | finite_subset [of _ "Pow (insert x F)", standard]) | |
| 1052 | apply (blast intro: finite_Pow_iff [THEN iffD2, THEN [2] finite_subset]) | |
| 1053 | done | |
| 1054 | ||
| 13421 | 1055 | theorem n_subsets: | 
| 1056 |     "finite A ==> card {B. B <= A & card B = k} = (card A choose k)"
 | |
| 12396 | 1057 | by (simp add: n_sub_lemma) | 
| 1058 | ||
| 1059 | end |