1(* Title: HOL/Library/FuncSet.thy 2 Author: Florian Kammueller and Lawrence C Paulson, Lukas Bulwahn 3*) 4 5section \<open>Pi and Function Sets\<close> 6 7theory FuncSet 8 imports Main 9 abbrevs PiE = "Pi\<^sub>E" 10 and PIE = "\<Pi>\<^sub>E" 11begin 12 13definition Pi :: "'a set \<Rightarrow> ('a \<Rightarrow> 'b set) \<Rightarrow> ('a \<Rightarrow> 'b) set" 14 where "Pi A B = {f. \<forall>x. x \<in> A \<longrightarrow> f x \<in> B x}" 15 16definition extensional :: "'a set \<Rightarrow> ('a \<Rightarrow> 'b) set" 17 where "extensional A = {f. \<forall>x. x \<notin> A \<longrightarrow> f x = undefined}" 18 19definition "restrict" :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a set \<Rightarrow> 'a \<Rightarrow> 'b" 20 where "restrict f A = (\<lambda>x. if x \<in> A then f x else undefined)" 21 22abbreviation funcset :: "'a set \<Rightarrow> 'b set \<Rightarrow> ('a \<Rightarrow> 'b) set" (infixr "\<rightarrow>" 60) 23 where "A \<rightarrow> B \<equiv> Pi A (\<lambda>_. B)" 24 25syntax 26 "_Pi" :: "pttrn \<Rightarrow> 'a set \<Rightarrow> 'b set \<Rightarrow> ('a \<Rightarrow> 'b) set" ("(3\<Pi> _\<in>_./ _)" 10) 27 "_lam" :: "pttrn \<Rightarrow> 'a set \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> 'b)" ("(3\<lambda>_\<in>_./ _)" [0,0,3] 3) 28translations 29 "\<Pi> x\<in>A. B" \<rightleftharpoons> "CONST Pi A (\<lambda>x. B)" 30 "\<lambda>x\<in>A. f" \<rightleftharpoons> "CONST restrict (\<lambda>x. f) A" 31 32definition "compose" :: "'a set \<Rightarrow> ('b \<Rightarrow> 'c) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> 'c)" 33 where "compose A g f = (\<lambda>x\<in>A. g (f x))" 34 35 36subsection \<open>Basic Properties of \<^term>\<open>Pi\<close>\<close> 37 38lemma Pi_I[intro!]: "(\<And>x. x \<in> A \<Longrightarrow> f x \<in> B x) \<Longrightarrow> f \<in> Pi A B" 39 by (simp add: Pi_def) 40 41lemma Pi_I'[simp]: "(\<And>x. x \<in> A \<longrightarrow> f x \<in> B x) \<Longrightarrow> f \<in> Pi A B" 42 by (simp add:Pi_def) 43 44lemma funcsetI: "(\<And>x. x \<in> A \<Longrightarrow> f x \<in> B) \<Longrightarrow> f \<in> A \<rightarrow> B" 45 by (simp add: Pi_def) 46 47lemma Pi_mem: "f \<in> Pi A B \<Longrightarrow> x \<in> A \<Longrightarrow> f x \<in> B x" 48 by (simp add: Pi_def) 49 50lemma Pi_iff: "f \<in> Pi I X \<longleftrightarrow> (\<forall>i\<in>I. f i \<in> X i)" 51 unfolding Pi_def by auto 52 53lemma PiE [elim]: "f \<in> Pi A B \<Longrightarrow> (f x \<in> B x \<Longrightarrow> Q) \<Longrightarrow> (x \<notin> A \<Longrightarrow> Q) \<Longrightarrow> Q" 54 by (auto simp: Pi_def) 55 56lemma Pi_cong: "(\<And>w. w \<in> A \<Longrightarrow> f w = g w) \<Longrightarrow> f \<in> Pi A B \<longleftrightarrow> g \<in> Pi A B" 57 by (auto simp: Pi_def) 58 59lemma funcset_id [simp]: "(\<lambda>x. x) \<in> A \<rightarrow> A" 60 by auto 61 62lemma funcset_mem: "f \<in> A \<rightarrow> B \<Longrightarrow> x \<in> A \<Longrightarrow> f x \<in> B" 63 by (simp add: Pi_def) 64 65lemma funcset_image: "f \<in> A \<rightarrow> B \<Longrightarrow> f ` A \<subseteq> B" 66 by auto 67 68lemma image_subset_iff_funcset: "F ` A \<subseteq> B \<longleftrightarrow> F \<in> A \<rightarrow> B" 69 by auto 70 71lemma funcset_to_empty_iff: "A \<rightarrow> {} = (if A={} then UNIV else {})" 72 by auto 73 74lemma Pi_eq_empty[simp]: "(\<Pi> x \<in> A. B x) = {} \<longleftrightarrow> (\<exists>x\<in>A. B x = {})" 75proof - 76 have "\<exists>x\<in>A. B x = {}" if "\<And>f. \<exists>y. y \<in> A \<and> f y \<notin> B y" 77 using that [of "\<lambda>u. SOME y. y \<in> B u"] some_in_eq by blast 78 then show ?thesis 79 by force 80qed 81 82lemma Pi_empty [simp]: "Pi {} B = UNIV" 83 by (simp add: Pi_def) 84 85lemma Pi_Int: "Pi I E \<inter> Pi I F = (\<Pi> i\<in>I. E i \<inter> F i)" 86 by auto 87 88lemma Pi_UN: 89 fixes A :: "nat \<Rightarrow> 'i \<Rightarrow> 'a set" 90 assumes "finite I" 91 and mono: "\<And>i n m. i \<in> I \<Longrightarrow> n \<le> m \<Longrightarrow> A n i \<subseteq> A m i" 92 shows "(\<Union>n. Pi I (A n)) = (\<Pi> i\<in>I. \<Union>n. A n i)" 93proof (intro set_eqI iffI) 94 fix f 95 assume "f \<in> (\<Pi> i\<in>I. \<Union>n. A n i)" 96 then have "\<forall>i\<in>I. \<exists>n. f i \<in> A n i" 97 by auto 98 from bchoice[OF this] obtain n where n: "f i \<in> A (n i) i" if "i \<in> I" for i 99 by auto 100 obtain k where k: "n i \<le> k" if "i \<in> I" for i 101 using \<open>finite I\<close> finite_nat_set_iff_bounded_le[of "n`I"] by auto 102 have "f \<in> Pi I (A k)" 103 proof (intro Pi_I) 104 fix i 105 assume "i \<in> I" 106 from mono[OF this, of "n i" k] k[OF this] n[OF this] 107 show "f i \<in> A k i" by auto 108 qed 109 then show "f \<in> (\<Union>n. Pi I (A n))" 110 by auto 111qed auto 112 113lemma Pi_UNIV [simp]: "A \<rightarrow> UNIV = UNIV" 114 by (simp add: Pi_def) 115 116text \<open>Covariance of Pi-sets in their second argument\<close> 117lemma Pi_mono: "(\<And>x. x \<in> A \<Longrightarrow> B x \<subseteq> C x) \<Longrightarrow> Pi A B \<subseteq> Pi A C" 118 by auto 119 120text \<open>Contravariance of Pi-sets in their first argument\<close> 121lemma Pi_anti_mono: "A' \<subseteq> A \<Longrightarrow> Pi A B \<subseteq> Pi A' B" 122 by auto 123 124lemma prod_final: 125 assumes 1: "fst \<circ> f \<in> Pi A B" 126 and 2: "snd \<circ> f \<in> Pi A C" 127 shows "f \<in> (\<Pi> z \<in> A. B z \<times> C z)" 128proof (rule Pi_I) 129 fix z 130 assume z: "z \<in> A" 131 have "f z = (fst (f z), snd (f z))" 132 by simp 133 also have "\<dots> \<in> B z \<times> C z" 134 by (metis SigmaI PiE o_apply 1 2 z) 135 finally show "f z \<in> B z \<times> C z" . 136qed 137 138lemma Pi_split_domain[simp]: "x \<in> Pi (I \<union> J) X \<longleftrightarrow> x \<in> Pi I X \<and> x \<in> Pi J X" 139 by (auto simp: Pi_def) 140 141lemma Pi_split_insert_domain[simp]: "x \<in> Pi (insert i I) X \<longleftrightarrow> x \<in> Pi I X \<and> x i \<in> X i" 142 by (auto simp: Pi_def) 143 144lemma Pi_cancel_fupd_range[simp]: "i \<notin> I \<Longrightarrow> x \<in> Pi I (B(i := b)) \<longleftrightarrow> x \<in> Pi I B" 145 by (auto simp: Pi_def) 146 147lemma Pi_cancel_fupd[simp]: "i \<notin> I \<Longrightarrow> x(i := a) \<in> Pi I B \<longleftrightarrow> x \<in> Pi I B" 148 by (auto simp: Pi_def) 149 150lemma Pi_fupd_iff: "i \<in> I \<Longrightarrow> f \<in> Pi I (B(i := A)) \<longleftrightarrow> f \<in> Pi (I - {i}) B \<and> f i \<in> A" 151 apply auto 152 apply (metis PiE fun_upd_apply) 153 by force 154 155 156subsection \<open>Composition With a Restricted Domain: \<^term>\<open>compose\<close>\<close> 157 158lemma funcset_compose: "f \<in> A \<rightarrow> B \<Longrightarrow> g \<in> B \<rightarrow> C \<Longrightarrow> compose A g f \<in> A \<rightarrow> C" 159 by (simp add: Pi_def compose_def restrict_def) 160 161lemma compose_assoc: 162 assumes "f \<in> A \<rightarrow> B" 163 shows "compose A h (compose A g f) = compose A (compose B h g) f" 164 using assms by (simp add: fun_eq_iff Pi_def compose_def restrict_def) 165 166lemma compose_eq: "x \<in> A \<Longrightarrow> compose A g f x = g (f x)" 167 by (simp add: compose_def restrict_def) 168 169lemma surj_compose: "f ` A = B \<Longrightarrow> g ` B = C \<Longrightarrow> compose A g f ` A = C" 170 by (auto simp add: image_def compose_eq) 171 172 173subsection \<open>Bounded Abstraction: \<^term>\<open>restrict\<close>\<close> 174 175lemma restrict_cong: "I = J \<Longrightarrow> (\<And>i. i \<in> J =simp=> f i = g i) \<Longrightarrow> restrict f I = restrict g J" 176 by (auto simp: restrict_def fun_eq_iff simp_implies_def) 177 178lemma restrict_in_funcset: "(\<And>x. x \<in> A \<Longrightarrow> f x \<in> B) \<Longrightarrow> (\<lambda>x\<in>A. f x) \<in> A \<rightarrow> B" 179 by (simp add: Pi_def restrict_def) 180 181lemma restrictI[intro!]: "(\<And>x. x \<in> A \<Longrightarrow> f x \<in> B x) \<Longrightarrow> (\<lambda>x\<in>A. f x) \<in> Pi A B" 182 by (simp add: Pi_def restrict_def) 183 184lemma restrict_apply[simp]: "(\<lambda>y\<in>A. f y) x = (if x \<in> A then f x else undefined)" 185 by (simp add: restrict_def) 186 187lemma restrict_apply': "x \<in> A \<Longrightarrow> (\<lambda>y\<in>A. f y) x = f x" 188 by simp 189 190lemma restrict_ext: "(\<And>x. x \<in> A \<Longrightarrow> f x = g x) \<Longrightarrow> (\<lambda>x\<in>A. f x) = (\<lambda>x\<in>A. g x)" 191 by (simp add: fun_eq_iff Pi_def restrict_def) 192 193lemma restrict_UNIV: "restrict f UNIV = f" 194 by (simp add: restrict_def) 195 196lemma inj_on_restrict_eq [simp]: "inj_on (restrict f A) A = inj_on f A" 197 by (simp add: inj_on_def restrict_def) 198 199lemma Id_compose: "f \<in> A \<rightarrow> B \<Longrightarrow> f \<in> extensional A \<Longrightarrow> compose A (\<lambda>y\<in>B. y) f = f" 200 by (auto simp add: fun_eq_iff compose_def extensional_def Pi_def) 201 202lemma compose_Id: "g \<in> A \<rightarrow> B \<Longrightarrow> g \<in> extensional A \<Longrightarrow> compose A g (\<lambda>x\<in>A. x) = g" 203 by (auto simp add: fun_eq_iff compose_def extensional_def Pi_def) 204 205lemma image_restrict_eq [simp]: "(restrict f A) ` A = f ` A" 206 by (auto simp add: restrict_def) 207 208lemma restrict_restrict[simp]: "restrict (restrict f A) B = restrict f (A \<inter> B)" 209 unfolding restrict_def by (simp add: fun_eq_iff) 210 211lemma restrict_fupd[simp]: "i \<notin> I \<Longrightarrow> restrict (f (i := x)) I = restrict f I" 212 by (auto simp: restrict_def) 213 214lemma restrict_upd[simp]: "i \<notin> I \<Longrightarrow> (restrict f I)(i := y) = restrict (f(i := y)) (insert i I)" 215 by (auto simp: fun_eq_iff) 216 217lemma restrict_Pi_cancel: "restrict x I \<in> Pi I A \<longleftrightarrow> x \<in> Pi I A" 218 by (auto simp: restrict_def Pi_def) 219 220lemma sum_restrict' [simp]: "sum' (\<lambda>i\<in>I. g i) I = sum' (\<lambda>i. g i) I" 221 by (simp add: sum.G_def conj_commute cong: conj_cong) 222 223lemma prod_restrict' [simp]: "prod' (\<lambda>i\<in>I. g i) I = prod' (\<lambda>i. g i) I" 224 by (simp add: prod.G_def conj_commute cong: conj_cong) 225 226 227subsection \<open>Bijections Between Sets\<close> 228 229text \<open>The definition of \<^const>\<open>bij_betw\<close> is in \<open>Fun.thy\<close>, but most of 230the theorems belong here, or need at least \<^term>\<open>Hilbert_Choice\<close>.\<close> 231 232lemma bij_betwI: 233 assumes "f \<in> A \<rightarrow> B" 234 and "g \<in> B \<rightarrow> A" 235 and g_f: "\<And>x. x\<in>A \<Longrightarrow> g (f x) = x" 236 and f_g: "\<And>y. y\<in>B \<Longrightarrow> f (g y) = y" 237 shows "bij_betw f A B" 238 unfolding bij_betw_def 239proof 240 show "inj_on f A" 241 by (metis g_f inj_on_def) 242 have "f ` A \<subseteq> B" 243 using \<open>f \<in> A \<rightarrow> B\<close> by auto 244 moreover 245 have "B \<subseteq> f ` A" 246 by auto (metis Pi_mem \<open>g \<in> B \<rightarrow> A\<close> f_g image_iff) 247 ultimately show "f ` A = B" 248 by blast 249qed 250 251lemma bij_betw_imp_funcset: "bij_betw f A B \<Longrightarrow> f \<in> A \<rightarrow> B" 252 by (auto simp add: bij_betw_def) 253 254lemma inj_on_compose: "bij_betw f A B \<Longrightarrow> inj_on g B \<Longrightarrow> inj_on (compose A g f) A" 255 by (auto simp add: bij_betw_def inj_on_def compose_eq) 256 257lemma bij_betw_compose: "bij_betw f A B \<Longrightarrow> bij_betw g B C \<Longrightarrow> bij_betw (compose A g f) A C" 258 apply (simp add: bij_betw_def compose_eq inj_on_compose) 259 apply (auto simp add: compose_def image_def) 260 done 261 262lemma bij_betw_restrict_eq [simp]: "bij_betw (restrict f A) A B = bij_betw f A B" 263 by (simp add: bij_betw_def) 264 265 266subsection \<open>Extensionality\<close> 267 268lemma extensional_empty[simp]: "extensional {} = {\<lambda>x. undefined}" 269 unfolding extensional_def by auto 270 271lemma extensional_arb: "f \<in> extensional A \<Longrightarrow> x \<notin> A \<Longrightarrow> f x = undefined" 272 by (simp add: extensional_def) 273 274lemma restrict_extensional [simp]: "restrict f A \<in> extensional A" 275 by (simp add: restrict_def extensional_def) 276 277lemma compose_extensional [simp]: "compose A f g \<in> extensional A" 278 by (simp add: compose_def) 279 280lemma extensionalityI: 281 assumes "f \<in> extensional A" 282 and "g \<in> extensional A" 283 and "\<And>x. x \<in> A \<Longrightarrow> f x = g x" 284 shows "f = g" 285 using assms by (force simp add: fun_eq_iff extensional_def) 286 287lemma extensional_restrict: "f \<in> extensional A \<Longrightarrow> restrict f A = f" 288 by (rule extensionalityI[OF restrict_extensional]) auto 289 290lemma extensional_subset: "f \<in> extensional A \<Longrightarrow> A \<subseteq> B \<Longrightarrow> f \<in> extensional B" 291 unfolding extensional_def by auto 292 293lemma inv_into_funcset: "f ` A = B \<Longrightarrow> (\<lambda>x\<in>B. inv_into A f x) \<in> B \<rightarrow> A" 294 by (unfold inv_into_def) (fast intro: someI2) 295 296lemma compose_inv_into_id: "bij_betw f A B \<Longrightarrow> compose A (\<lambda>y\<in>B. inv_into A f y) f = (\<lambda>x\<in>A. x)" 297 apply (simp add: bij_betw_def compose_def) 298 apply (rule restrict_ext, auto) 299 done 300 301lemma compose_id_inv_into: "f ` A = B \<Longrightarrow> compose B f (\<lambda>y\<in>B. inv_into A f y) = (\<lambda>x\<in>B. x)" 302 apply (simp add: compose_def) 303 apply (rule restrict_ext) 304 apply (simp add: f_inv_into_f) 305 done 306 307lemma extensional_insert[intro, simp]: 308 assumes "a \<in> extensional (insert i I)" 309 shows "a(i := b) \<in> extensional (insert i I)" 310 using assms unfolding extensional_def by auto 311 312lemma extensional_Int[simp]: "extensional I \<inter> extensional I' = extensional (I \<inter> I')" 313 unfolding extensional_def by auto 314 315lemma extensional_UNIV[simp]: "extensional UNIV = UNIV" 316 by (auto simp: extensional_def) 317 318lemma restrict_extensional_sub[intro]: "A \<subseteq> B \<Longrightarrow> restrict f A \<in> extensional B" 319 unfolding restrict_def extensional_def by auto 320 321lemma extensional_insert_undefined[intro, simp]: 322 "a \<in> extensional (insert i I) \<Longrightarrow> a(i := undefined) \<in> extensional I" 323 unfolding extensional_def by auto 324 325lemma extensional_insert_cancel[intro, simp]: 326 "a \<in> extensional I \<Longrightarrow> a \<in> extensional (insert i I)" 327 unfolding extensional_def by auto 328 329 330subsection \<open>Cardinality\<close> 331 332lemma card_inj: "f \<in> A \<rightarrow> B \<Longrightarrow> inj_on f A \<Longrightarrow> finite B \<Longrightarrow> card A \<le> card B" 333 by (rule card_inj_on_le) auto 334 335lemma card_bij: 336 assumes "f \<in> A \<rightarrow> B" "inj_on f A" 337 and "g \<in> B \<rightarrow> A" "inj_on g B" 338 and "finite A" "finite B" 339 shows "card A = card B" 340 using assms by (blast intro: card_inj order_antisym) 341 342 343subsection \<open>Extensional Function Spaces\<close> 344 345definition PiE :: "'a set \<Rightarrow> ('a \<Rightarrow> 'b set) \<Rightarrow> ('a \<Rightarrow> 'b) set" 346 where "PiE S T = Pi S T \<inter> extensional S" 347 348abbreviation "Pi\<^sub>E A B \<equiv> PiE A B" 349 350syntax 351 "_PiE" :: "pttrn \<Rightarrow> 'a set \<Rightarrow> 'b set \<Rightarrow> ('a \<Rightarrow> 'b) set" ("(3\<Pi>\<^sub>E _\<in>_./ _)" 10) 352translations 353 "\<Pi>\<^sub>E x\<in>A. B" \<rightleftharpoons> "CONST Pi\<^sub>E A (\<lambda>x. B)" 354 355abbreviation extensional_funcset :: "'a set \<Rightarrow> 'b set \<Rightarrow> ('a \<Rightarrow> 'b) set" (infixr "\<rightarrow>\<^sub>E" 60) 356 where "A \<rightarrow>\<^sub>E B \<equiv> (\<Pi>\<^sub>E i\<in>A. B)" 357 358lemma extensional_funcset_def: "extensional_funcset S T = (S \<rightarrow> T) \<inter> extensional S" 359 by (simp add: PiE_def) 360 361lemma PiE_empty_domain[simp]: "Pi\<^sub>E {} T = {\<lambda>x. undefined}" 362 unfolding PiE_def by simp 363 364lemma PiE_UNIV_domain: "Pi\<^sub>E UNIV T = Pi UNIV T" 365 unfolding PiE_def by simp 366 367lemma PiE_empty_range[simp]: "i \<in> I \<Longrightarrow> F i = {} \<Longrightarrow> (\<Pi>\<^sub>E i\<in>I. F i) = {}" 368 unfolding PiE_def by auto 369 370lemma PiE_eq_empty_iff: "Pi\<^sub>E I F = {} \<longleftrightarrow> (\<exists>i\<in>I. F i = {})" 371proof 372 assume "Pi\<^sub>E I F = {}" 373 show "\<exists>i\<in>I. F i = {}" 374 proof (rule ccontr) 375 assume "\<not> ?thesis" 376 then have "\<forall>i. \<exists>y. (i \<in> I \<longrightarrow> y \<in> F i) \<and> (i \<notin> I \<longrightarrow> y = undefined)" 377 by auto 378 from choice[OF this] 379 obtain f where " \<forall>x. (x \<in> I \<longrightarrow> f x \<in> F x) \<and> (x \<notin> I \<longrightarrow> f x = undefined)" .. 380 then have "f \<in> Pi\<^sub>E I F" 381 by (auto simp: extensional_def PiE_def) 382 with \<open>Pi\<^sub>E I F = {}\<close> show False 383 by auto 384 qed 385qed (auto simp: PiE_def) 386 387lemma PiE_arb: "f \<in> Pi\<^sub>E S T \<Longrightarrow> x \<notin> S \<Longrightarrow> f x = undefined" 388 unfolding PiE_def by auto (auto dest!: extensional_arb) 389 390lemma PiE_mem: "f \<in> Pi\<^sub>E S T \<Longrightarrow> x \<in> S \<Longrightarrow> f x \<in> T x" 391 unfolding PiE_def by auto 392 393lemma PiE_fun_upd: "y \<in> T x \<Longrightarrow> f \<in> Pi\<^sub>E S T \<Longrightarrow> f(x := y) \<in> Pi\<^sub>E (insert x S) T" 394 unfolding PiE_def extensional_def by auto 395 396lemma fun_upd_in_PiE: "x \<notin> S \<Longrightarrow> f \<in> Pi\<^sub>E (insert x S) T \<Longrightarrow> f(x := undefined) \<in> Pi\<^sub>E S T" 397 unfolding PiE_def extensional_def by auto 398 399lemma PiE_insert_eq: "Pi\<^sub>E (insert x S) T = (\<lambda>(y, g). g(x := y)) ` (T x \<times> Pi\<^sub>E S T)" 400proof - 401 { 402 fix f assume "f \<in> Pi\<^sub>E (insert x S) T" "x \<notin> S" 403 then have "f \<in> (\<lambda>(y, g). g(x := y)) ` (T x \<times> Pi\<^sub>E S T)" 404 by (auto intro!: image_eqI[where x="(f x, f(x := undefined))"] intro: fun_upd_in_PiE PiE_mem) 405 } 406 moreover 407 { 408 fix f assume "f \<in> Pi\<^sub>E (insert x S) T" "x \<in> S" 409 then have "f \<in> (\<lambda>(y, g). g(x := y)) ` (T x \<times> Pi\<^sub>E S T)" 410 by (auto intro!: image_eqI[where x="(f x, f)"] intro: fun_upd_in_PiE PiE_mem simp: insert_absorb) 411 } 412 ultimately show ?thesis 413 by (auto intro: PiE_fun_upd) 414qed 415 416lemma PiE_Int: "Pi\<^sub>E I A \<inter> Pi\<^sub>E I B = Pi\<^sub>E I (\<lambda>x. A x \<inter> B x)" 417 by (auto simp: PiE_def) 418 419lemma PiE_cong: "(\<And>i. i\<in>I \<Longrightarrow> A i = B i) \<Longrightarrow> Pi\<^sub>E I A = Pi\<^sub>E I B" 420 unfolding PiE_def by (auto simp: Pi_cong) 421 422lemma PiE_E [elim]: 423 assumes "f \<in> Pi\<^sub>E A B" 424 obtains "x \<in> A" and "f x \<in> B x" 425 | "x \<notin> A" and "f x = undefined" 426 using assms by (auto simp: Pi_def PiE_def extensional_def) 427 428lemma PiE_I[intro!]: 429 "(\<And>x. x \<in> A \<Longrightarrow> f x \<in> B x) \<Longrightarrow> (\<And>x. x \<notin> A \<Longrightarrow> f x = undefined) \<Longrightarrow> f \<in> Pi\<^sub>E A B" 430 by (simp add: PiE_def extensional_def) 431 432lemma PiE_mono: "(\<And>x. x \<in> A \<Longrightarrow> B x \<subseteq> C x) \<Longrightarrow> Pi\<^sub>E A B \<subseteq> Pi\<^sub>E A C" 433 by auto 434 435lemma PiE_iff: "f \<in> Pi\<^sub>E I X \<longleftrightarrow> (\<forall>i\<in>I. f i \<in> X i) \<and> f \<in> extensional I" 436 by (simp add: PiE_def Pi_iff) 437 438lemma ext_funcset_to_sing_iff [simp]: "A \<rightarrow>\<^sub>E {a} = {\<lambda>x\<in>A. a}" 439 by (auto simp: PiE_def Pi_iff extensionalityI) 440 441lemma PiE_restrict[simp]: "f \<in> Pi\<^sub>E A B \<Longrightarrow> restrict f A = f" 442 by (simp add: extensional_restrict PiE_def) 443 444lemma restrict_PiE[simp]: "restrict f I \<in> Pi\<^sub>E I S \<longleftrightarrow> f \<in> Pi I S" 445 by (auto simp: PiE_iff) 446 447lemma PiE_eq_subset: 448 assumes ne: "\<And>i. i \<in> I \<Longrightarrow> F i \<noteq> {}" "\<And>i. i \<in> I \<Longrightarrow> F' i \<noteq> {}" 449 and eq: "Pi\<^sub>E I F = Pi\<^sub>E I F'" 450 and "i \<in> I" 451 shows "F i \<subseteq> F' i" 452proof 453 fix x 454 assume "x \<in> F i" 455 with ne have "\<forall>j. \<exists>y. (j \<in> I \<longrightarrow> y \<in> F j \<and> (i = j \<longrightarrow> x = y)) \<and> (j \<notin> I \<longrightarrow> y = undefined)" 456 by auto 457 from choice[OF this] obtain f 458 where f: " \<forall>j. (j \<in> I \<longrightarrow> f j \<in> F j \<and> (i = j \<longrightarrow> x = f j)) \<and> (j \<notin> I \<longrightarrow> f j = undefined)" .. 459 then have "f \<in> Pi\<^sub>E I F" 460 by (auto simp: extensional_def PiE_def) 461 then have "f \<in> Pi\<^sub>E I F'" 462 using assms by simp 463 then show "x \<in> F' i" 464 using f \<open>i \<in> I\<close> by (auto simp: PiE_def) 465qed 466 467lemma PiE_eq_iff_not_empty: 468 assumes ne: "\<And>i. i \<in> I \<Longrightarrow> F i \<noteq> {}" "\<And>i. i \<in> I \<Longrightarrow> F' i \<noteq> {}" 469 shows "Pi\<^sub>E I F = Pi\<^sub>E I F' \<longleftrightarrow> (\<forall>i\<in>I. F i = F' i)" 470proof (intro iffI ballI) 471 fix i 472 assume eq: "Pi\<^sub>E I F = Pi\<^sub>E I F'" 473 assume i: "i \<in> I" 474 show "F i = F' i" 475 using PiE_eq_subset[of I F F', OF ne eq i] 476 using PiE_eq_subset[of I F' F, OF ne(2,1) eq[symmetric] i] 477 by auto 478qed (auto simp: PiE_def) 479 480lemma PiE_eq_iff: 481 "Pi\<^sub>E I F = Pi\<^sub>E I F' \<longleftrightarrow> (\<forall>i\<in>I. F i = F' i) \<or> ((\<exists>i\<in>I. F i = {}) \<and> (\<exists>i\<in>I. F' i = {}))" 482proof (intro iffI disjCI) 483 assume eq[simp]: "Pi\<^sub>E I F = Pi\<^sub>E I F'" 484 assume "\<not> ((\<exists>i\<in>I. F i = {}) \<and> (\<exists>i\<in>I. F' i = {}))" 485 then have "(\<forall>i\<in>I. F i \<noteq> {}) \<and> (\<forall>i\<in>I. F' i \<noteq> {})" 486 using PiE_eq_empty_iff[of I F] PiE_eq_empty_iff[of I F'] by auto 487 with PiE_eq_iff_not_empty[of I F F'] show "\<forall>i\<in>I. F i = F' i" 488 by auto 489next 490 assume "(\<forall>i\<in>I. F i = F' i) \<or> (\<exists>i\<in>I. F i = {}) \<and> (\<exists>i\<in>I. F' i = {})" 491 then show "Pi\<^sub>E I F = Pi\<^sub>E I F'" 492 using PiE_eq_empty_iff[of I F] PiE_eq_empty_iff[of I F'] by (auto simp: PiE_def) 493qed 494 495lemma extensional_funcset_fun_upd_restricts_rangeI: 496 "\<forall>y \<in> S. f x \<noteq> f y \<Longrightarrow> f \<in> (insert x S) \<rightarrow>\<^sub>E T \<Longrightarrow> f(x := undefined) \<in> S \<rightarrow>\<^sub>E (T - {f x})" 497 unfolding extensional_funcset_def extensional_def 498 apply auto 499 apply (case_tac "x = xa") 500 apply auto 501 done 502 503lemma extensional_funcset_fun_upd_extends_rangeI: 504 assumes "a \<in> T" "f \<in> S \<rightarrow>\<^sub>E (T - {a})" 505 shows "f(x := a) \<in> insert x S \<rightarrow>\<^sub>E T" 506 using assms unfolding extensional_funcset_def extensional_def by auto 507 508lemma subset_PiE: 509 "PiE I S \<subseteq> PiE I T \<longleftrightarrow> PiE I S = {} \<or> (\<forall>i \<in> I. S i \<subseteq> T i)" (is "?lhs \<longleftrightarrow> _ \<or> ?rhs") 510proof (cases "PiE I S = {}") 511 case False 512 moreover have "?lhs = ?rhs" 513 proof 514 assume L: ?lhs 515 have "\<And>i. i\<in>I \<Longrightarrow> S i \<noteq> {}" 516 using False PiE_eq_empty_iff by blast 517 with L show ?rhs 518 by (simp add: PiE_Int PiE_eq_iff inf.absorb_iff2) 519 qed auto 520 ultimately show ?thesis 521 by simp 522qed simp 523 524lemma PiE_eq: 525 "PiE I S = PiE I T \<longleftrightarrow> PiE I S = {} \<and> PiE I T = {} \<or> (\<forall>i \<in> I. S i = T i)" 526 by (auto simp: PiE_eq_iff PiE_eq_empty_iff) 527 528lemma PiE_UNIV [simp]: "PiE UNIV (\<lambda>i. UNIV) = UNIV" 529 by blast 530 531lemma image_projection_PiE: 532 "(\<lambda>f. f i) ` (PiE I S) = (if PiE I S = {} then {} else if i \<in> I then S i else {undefined})" 533proof - 534 have "(\<lambda>f. f i) ` Pi\<^sub>E I S = S i" if "i \<in> I" "f \<in> PiE I S" for f 535 using that apply auto 536 by (rule_tac x="(\<lambda>k. if k=i then x else f k)" in image_eqI) auto 537 moreover have "(\<lambda>f. f i) ` Pi\<^sub>E I S = {undefined}" if "f \<in> PiE I S" "i \<notin> I" for f 538 using that by (blast intro: PiE_arb [OF that, symmetric]) 539 ultimately show ?thesis 540 by auto 541qed 542 543lemma PiE_singleton: 544 assumes "f \<in> extensional A" 545 shows "PiE A (\<lambda>x. {f x}) = {f}" 546proof - 547 { 548 fix g assume "g \<in> PiE A (\<lambda>x. {f x})" 549 hence "g x = f x" for x 550 using assms by (cases "x \<in> A") (auto simp: extensional_def) 551 hence "g = f" by (simp add: fun_eq_iff) 552 } 553 thus ?thesis using assms by (auto simp: extensional_def) 554qed 555 556lemma PiE_eq_singleton: "(\<Pi>\<^sub>E i\<in>I. S i) = {\<lambda>i\<in>I. f i} \<longleftrightarrow> (\<forall>i\<in>I. S i = {f i})" 557 by (metis (mono_tags, lifting) PiE_eq PiE_singleton insert_not_empty restrict_apply' restrict_extensional) 558 559lemma PiE_over_singleton_iff: "(\<Pi>\<^sub>E x\<in>{a}. B x) = (\<Union>b \<in> B a. {\<lambda>x \<in> {a}. b})" 560 apply (auto simp: PiE_iff split: if_split_asm) 561 apply (metis (no_types, lifting) extensionalityI restrict_apply' restrict_extensional singletonD) 562 done 563 564lemma all_PiE_elements: 565 "(\<forall>z \<in> PiE I S. \<forall>i \<in> I. P i (z i)) \<longleftrightarrow> PiE I S = {} \<or> (\<forall>i \<in> I. \<forall>x \<in> S i. P i x)" (is "?lhs = ?rhs") 566proof (cases "PiE I S = {}") 567 case False 568 then obtain f where f: "\<And>i. i \<in> I \<Longrightarrow> f i \<in> S i" 569 by fastforce 570 show ?thesis 571 proof 572 assume L: ?lhs 573 have "P i x" 574 if "i \<in> I" "x \<in> S i" for i x 575 proof - 576 have "(\<lambda>j \<in> I. if j=i then x else f j) \<in> PiE I S" 577 by (simp add: f that(2)) 578 then have "P i ((\<lambda>j \<in> I. if j=i then x else f j) i)" 579 using L that(1) by blast 580 with that show ?thesis 581 by simp 582 qed 583 then show ?rhs 584 by (simp add: False) 585 qed fastforce 586qed simp 587 588lemma PiE_ext: "\<lbrakk>x \<in> PiE k s; y \<in> PiE k s; \<And>i. i \<in> k \<Longrightarrow> x i = y i\<rbrakk> \<Longrightarrow> x = y" 589 by (metis ext PiE_E) 590 591 592subsubsection \<open>Injective Extensional Function Spaces\<close> 593 594lemma extensional_funcset_fun_upd_inj_onI: 595 assumes "f \<in> S \<rightarrow>\<^sub>E (T - {a})" 596 and "inj_on f S" 597 shows "inj_on (f(x := a)) S" 598 using assms 599 unfolding extensional_funcset_def by (auto intro!: inj_on_fun_updI) 600 601lemma extensional_funcset_extend_domain_inj_on_eq: 602 assumes "x \<notin> S" 603 shows "{f. f \<in> (insert x S) \<rightarrow>\<^sub>E T \<and> inj_on f (insert x S)} = 604 (\<lambda>(y, g). g(x:=y)) ` {(y, g). y \<in> T \<and> g \<in> S \<rightarrow>\<^sub>E (T - {y}) \<and> inj_on g S}" 605 using assms 606 apply (auto del: PiE_I PiE_E) 607 apply (auto intro: extensional_funcset_fun_upd_inj_onI 608 extensional_funcset_fun_upd_extends_rangeI del: PiE_I PiE_E) 609 apply (auto simp add: image_iff inj_on_def) 610 apply (rule_tac x="xa x" in exI) 611 apply (auto intro: PiE_mem del: PiE_I PiE_E) 612 apply (rule_tac x="xa(x := undefined)" in exI) 613 apply (auto intro!: extensional_funcset_fun_upd_restricts_rangeI) 614 apply (auto dest!: PiE_mem split: if_split_asm) 615 done 616 617lemma extensional_funcset_extend_domain_inj_onI: 618 assumes "x \<notin> S" 619 shows "inj_on (\<lambda>(y, g). g(x := y)) {(y, g). y \<in> T \<and> g \<in> S \<rightarrow>\<^sub>E (T - {y}) \<and> inj_on g S}" 620 using assms 621 apply (auto intro!: inj_onI) 622 apply (metis fun_upd_same) 623 apply (metis assms PiE_arb fun_upd_triv fun_upd_upd) 624 done 625 626 627subsubsection \<open>Misc properties of functions, composition and restriction from HOL Light\<close> 628 629lemma function_factors_left_gen: 630 "(\<forall>x y. P x \<and> P y \<and> g x = g y \<longrightarrow> f x = f y) \<longleftrightarrow> (\<exists>h. \<forall>x. P x \<longrightarrow> f x = h(g x))" 631 (is "?lhs = ?rhs") 632proof 633 assume L: ?lhs 634 then show ?rhs 635 apply (rule_tac x="f \<circ> inv_into (Collect P) g" in exI) 636 unfolding o_def 637 by (metis (mono_tags, hide_lams) f_inv_into_f imageI inv_into_into mem_Collect_eq) 638qed auto 639 640lemma function_factors_left: 641 "(\<forall>x y. (g x = g y) \<longrightarrow> (f x = f y)) \<longleftrightarrow> (\<exists>h. f = h \<circ> g)" 642 using function_factors_left_gen [of "\<lambda>x. True" g f] unfolding o_def by blast 643 644lemma function_factors_right_gen: 645 "(\<forall>x. P x \<longrightarrow> (\<exists>y. g y = f x)) \<longleftrightarrow> (\<exists>h. \<forall>x. P x \<longrightarrow> f x = g(h x))" 646 by metis 647 648lemma function_factors_right: 649 "(\<forall>x. \<exists>y. g y = f x) \<longleftrightarrow> (\<exists>h. f = g \<circ> h)" 650 unfolding o_def by metis 651 652lemma restrict_compose_right: 653 "restrict (g \<circ> restrict f S) S = restrict (g \<circ> f) S" 654 by auto 655 656lemma restrict_compose_left: 657 "f ` S \<subseteq> T \<Longrightarrow> restrict (restrict g T \<circ> f) S = restrict (g \<circ> f) S" 658 by fastforce 659 660 661subsubsection \<open>Cardinality\<close> 662 663lemma finite_PiE: "finite S \<Longrightarrow> (\<And>i. i \<in> S \<Longrightarrow> finite (T i)) \<Longrightarrow> finite (\<Pi>\<^sub>E i \<in> S. T i)" 664 by (induct S arbitrary: T rule: finite_induct) (simp_all add: PiE_insert_eq) 665 666lemma inj_combinator: "x \<notin> S \<Longrightarrow> inj_on (\<lambda>(y, g). g(x := y)) (T x \<times> Pi\<^sub>E S T)" 667proof (safe intro!: inj_onI ext) 668 fix f y g z 669 assume "x \<notin> S" 670 assume fg: "f \<in> Pi\<^sub>E S T" "g \<in> Pi\<^sub>E S T" 671 assume "f(x := y) = g(x := z)" 672 then have *: "\<And>i. (f(x := y)) i = (g(x := z)) i" 673 unfolding fun_eq_iff by auto 674 from this[of x] show "y = z" by simp 675 fix i from *[of i] \<open>x \<notin> S\<close> fg show "f i = g i" 676 by (auto split: if_split_asm simp: PiE_def extensional_def) 677qed 678 679lemma card_PiE: "finite S \<Longrightarrow> card (\<Pi>\<^sub>E i \<in> S. T i) = (\<Prod> i\<in>S. card (T i))" 680proof (induct rule: finite_induct) 681 case empty 682 then show ?case by auto 683next 684 case (insert x S) 685 then show ?case 686 by (simp add: PiE_insert_eq inj_combinator card_image card_cartesian_product) 687qed 688 689end 690