clasohm@1475: (* Title: HOL/Fun.thy clasohm@1475: Author: Tobias Nipkow, Cambridge University Computer Laboratory blanchet@55019: Author: Andrei Popescu, TU Muenchen blanchet@55019: Copyright 1994, 2012 huffman@18154: *) clasohm@923: wenzelm@60758: section \Notions about functions\ clasohm@923: paulson@15510: theory Fun haftmann@56015: imports Set blanchet@55467: keywords "functor" :: thy_goal nipkow@15131: begin nipkow@2912: haftmann@26147: lemma apply_inverse: haftmann@26357: "f x = u \ (\x. P x \ g (f x) = x) \ P x \ x = g u" haftmann@26147: by auto nipkow@2912: wenzelm@60758: text\Uniqueness, so NOT the axiom of choice.\ lp15@59504: lemma uniq_choice: "\x. \!y. Q x y \ \f. \x. Q x (f x)" lp15@59504: by (force intro: theI') lp15@59504: lp15@59504: lemma b_uniq_choice: "\x\S. \!y. Q x y \ \f. \x\S. Q x (f x)" lp15@59504: by (force intro: theI') wenzelm@12258: wenzelm@61799: subsection \The Identity Function \id\\ paulson@6171: haftmann@44277: definition id :: "'a \ 'a" where haftmann@22744: "id = (\x. x)" nipkow@13910: haftmann@26147: lemma id_apply [simp]: "id x = x" haftmann@26147: by (simp add: id_def) haftmann@26147: huffman@47579: lemma image_id [simp]: "image id = id" huffman@47579: by (simp add: id_def fun_eq_iff) haftmann@26147: huffman@47579: lemma vimage_id [simp]: "vimage id = id" huffman@47579: by (simp add: id_def fun_eq_iff) haftmann@26147: haftmann@52435: code_printing haftmann@52435: constant id \ (Haskell) "id" haftmann@52435: haftmann@26147: wenzelm@61799: subsection \The Composition Operator \f \ g\\ haftmann@26147: wenzelm@61955: definition comp :: "('b \ 'c) \ ('a \ 'b) \ 'a \ 'c" (infixl "\" 55) wenzelm@61955: where "f \ g = (\x. f (g x))" oheimb@11123: wenzelm@61955: notation (ASCII) wenzelm@61955: comp (infixl "o" 55) wenzelm@19656: haftmann@49739: lemma comp_apply [simp]: "(f o g) x = f (g x)" haftmann@49739: by (simp add: comp_def) paulson@13585: haftmann@49739: lemma comp_assoc: "(f o g) o h = f o (g o h)" haftmann@49739: by (simp add: fun_eq_iff) paulson@13585: haftmann@49739: lemma id_comp [simp]: "id o g = g" haftmann@49739: by (simp add: fun_eq_iff) paulson@13585: haftmann@49739: lemma comp_id [simp]: "f o id = f" haftmann@49739: by (simp add: fun_eq_iff) haftmann@49739: haftmann@49739: lemma comp_eq_dest: haftmann@34150: "a o b = c o d \ a (b v) = c (d v)" haftmann@49739: by (simp add: fun_eq_iff) haftmann@34150: haftmann@49739: lemma comp_eq_elim: haftmann@34150: "a o b = c o d \ ((\v. a (b v) = c (d v)) \ R) \ R" paulson@61204: by (simp add: fun_eq_iff) haftmann@34150: blanchet@55066: lemma comp_eq_dest_lhs: "a o b = c \ a (b v) = c v" blanchet@55066: by clarsimp blanchet@55066: blanchet@55066: lemma comp_eq_id_dest: "a o b = id o c \ a (b v) = c v" blanchet@55066: by clarsimp blanchet@55066: haftmann@49739: lemma image_comp: haftmann@56154: "f ` (g ` r) = (f o g) ` r" paulson@33044: by auto paulson@33044: haftmann@49739: lemma vimage_comp: haftmann@56154: "f -` (g -` x) = (g \ f) -` x" haftmann@49739: by auto haftmann@49739: lp15@59504: lemma image_eq_imp_comp: "f ` A = g ` B \ (h o f) ` A = (h o g) ` B" lp15@59504: by (auto simp: comp_def elim!: equalityE) lp15@59504: Andreas@59512: lemma image_bind: "f ` (Set.bind A g) = Set.bind A (op ` f \ g)" Andreas@59512: by(auto simp add: Set.bind_def) Andreas@59512: Andreas@59512: lemma bind_image: "Set.bind (f ` A) g = Set.bind A (g \ f)" Andreas@59512: by(auto simp add: Set.bind_def) Andreas@59512: haftmann@60929: lemma (in group_add) minus_comp_minus [simp]: haftmann@60929: "uminus \ uminus = id" haftmann@60929: by (simp add: fun_eq_iff) haftmann@60929: haftmann@60929: lemma (in boolean_algebra) minus_comp_minus [simp]: haftmann@60929: "uminus \ uminus = id" haftmann@60929: by (simp add: fun_eq_iff) haftmann@60929: haftmann@52435: code_printing haftmann@52435: constant comp \ (SML) infixl 5 "o" and (Haskell) infixr 9 "." haftmann@52435: paulson@13585: wenzelm@61799: subsection \The Forward Composition Operator \fcomp\\ haftmann@26357: haftmann@44277: definition fcomp :: "('a \ 'b) \ ('b \ 'c) \ 'a \ 'c" (infixl "\>" 60) where haftmann@37751: "f \> g = (\x. g (f x))" haftmann@26357: haftmann@37751: lemma fcomp_apply [simp]: "(f \> g) x = g (f x)" haftmann@26357: by (simp add: fcomp_def) haftmann@26357: haftmann@37751: lemma fcomp_assoc: "(f \> g) \> h = f \> (g \> h)" haftmann@26357: by (simp add: fcomp_def) haftmann@26357: haftmann@37751: lemma id_fcomp [simp]: "id \> g = g" haftmann@26357: by (simp add: fcomp_def) haftmann@26357: haftmann@37751: lemma fcomp_id [simp]: "f \> id = f" haftmann@26357: by (simp add: fcomp_def) haftmann@26357: lp15@61699: lemma fcomp_comp: "fcomp f g = comp g f" lp15@61699: by (simp add: ext) lp15@61699: haftmann@52435: code_printing haftmann@52435: constant fcomp \ (Eval) infixl 1 "#>" haftmann@31202: haftmann@37751: no_notation fcomp (infixl "\>" 60) haftmann@26588: haftmann@26357: wenzelm@60758: subsection \Mapping functions\ haftmann@40602: haftmann@40602: definition map_fun :: "('c \ 'a) \ ('b \ 'd) \ ('a \ 'b) \ 'c \ 'd" where haftmann@40602: "map_fun f g h = g \ h \ f" haftmann@40602: haftmann@40602: lemma map_fun_apply [simp]: haftmann@40602: "map_fun f g h x = g (h (f x))" haftmann@40602: by (simp add: map_fun_def) haftmann@40602: haftmann@40602: wenzelm@60758: subsection \Injectivity and Bijectivity\ hoelzl@39076: wenzelm@61799: definition inj_on :: "('a \ 'b) \ 'a set \ bool" where \ "injective" hoelzl@39076: "inj_on f A \ (\x\A. \y\A. f x = f y \ x = y)" haftmann@26147: wenzelm@61799: definition bij_betw :: "('a \ 'b) \ 'a set \ 'b set \ bool" where \ "bijective" hoelzl@39076: "bij_betw f A B \ inj_on f A \ f ` A = B" haftmann@26147: wenzelm@60758: text\A common special case: functions injective, surjective or bijective over wenzelm@60758: the entire domain type.\ haftmann@26147: haftmann@26147: abbreviation hoelzl@39076: "inj f \ inj_on f UNIV" haftmann@26147: wenzelm@61799: abbreviation surj :: "('a \ 'b) \ bool" where \ "surjective" hoelzl@40702: "surj f \ (range f = UNIV)" paulson@13585: hoelzl@39076: abbreviation hoelzl@39076: "bij f \ bij_betw f UNIV UNIV" haftmann@26147: wenzelm@60758: text\The negated case:\ nipkow@43705: translations nipkow@43705: "\ CONST surj f" <= "CONST range f \ CONST UNIV" nipkow@43705: haftmann@26147: lemma injI: haftmann@26147: assumes "\x y. f x = f y \ x = y" haftmann@26147: shows "inj f" haftmann@26147: using assms unfolding inj_on_def by auto paulson@13585: berghofe@13637: theorem range_ex1_eq: "inj f \ b : range f = (EX! x. b = f x)" berghofe@13637: by (unfold inj_on_def, blast) berghofe@13637: paulson@13585: lemma injD: "[| inj(f); f(x) = f(y) |] ==> x=y" paulson@13585: by (simp add: inj_on_def) paulson@13585: lp15@61520: lemma inj_on_eq_iff: "\inj_on f A; x \ A; y \ A\ \ (f x = f y) = (x = y)" paulson@13585: by (force simp add: inj_on_def) paulson@13585: hoelzl@40703: lemma inj_on_cong: hoelzl@40703: "(\ a. a : A \ f a = g a) \ inj_on f A = inj_on g A" hoelzl@40703: unfolding inj_on_def by auto hoelzl@40703: hoelzl@40703: lemma inj_on_strict_subset: haftmann@56077: "inj_on f B \ A \ B \ f ` A \ f ` B" haftmann@56077: unfolding inj_on_def by blast hoelzl@40703: haftmann@38620: lemma inj_comp: haftmann@38620: "inj f \ inj g \ inj (f \ g)" haftmann@38620: by (simp add: inj_on_def) haftmann@38620: haftmann@38620: lemma inj_fun: "inj f \ inj (\x y. f x)" nipkow@39302: by (simp add: inj_on_def fun_eq_iff) haftmann@38620: nipkow@32988: lemma inj_eq: "inj f ==> (f(x) = f(y)) = (x=y)" nipkow@32988: by (simp add: inj_on_eq_iff) nipkow@32988: haftmann@26147: lemma inj_on_id[simp]: "inj_on id A" hoelzl@39076: by (simp add: inj_on_def) paulson@13585: haftmann@26147: lemma inj_on_id2[simp]: "inj_on (%x. x) A" hoelzl@39076: by (simp add: inj_on_def) haftmann@26147: bulwahn@46586: lemma inj_on_Int: "inj_on f A \ inj_on f B \ inj_on f (A \ B)" hoelzl@40703: unfolding inj_on_def by blast hoelzl@40703: hoelzl@40702: lemma surj_id: "surj id" hoelzl@40702: by simp haftmann@26147: hoelzl@39101: lemma bij_id[simp]: "bij id" hoelzl@39076: by (simp add: bij_betw_def) paulson@13585: paulson@13585: lemma inj_onI: paulson@13585: "(!! x y. [| x:A; y:A; f(x) = f(y) |] ==> x=y) ==> inj_on f A" paulson@13585: by (simp add: inj_on_def) paulson@13585: paulson@13585: lemma inj_on_inverseI: "(!!x. x:A ==> g(f(x)) = x) ==> inj_on f A" paulson@13585: by (auto dest: arg_cong [of concl: g] simp add: inj_on_def) paulson@13585: paulson@13585: lemma inj_onD: "[| inj_on f A; f(x)=f(y); x:A; y:A |] ==> x=y" paulson@13585: by (unfold inj_on_def, blast) paulson@13585: paulson@13585: lemma comp_inj_on: paulson@13585: "[| inj_on f A; inj_on g (f`A) |] ==> inj_on (g o f) A" paulson@13585: by (simp add: comp_def inj_on_def) paulson@13585: nipkow@15303: lemma inj_on_imageI: "inj_on (g o f) A \ inj_on g (f ` A)" haftmann@56077: by (simp add: inj_on_def) blast nipkow@15303: nipkow@15439: lemma inj_on_image_iff: "\ ALL x:A. ALL y:A. (g(f x) = g(f y)) = (g x = g y); nipkow@15439: inj_on f A \ \ inj_on g (f ` A) = inj_on g A" nipkow@15439: apply(unfold inj_on_def) nipkow@15439: apply blast nipkow@15439: done nipkow@15439: paulson@13585: lemma inj_on_contraD: "[| inj_on f A; ~x=y; x:A; y:A |] ==> ~ f(x)=f(y)" paulson@13585: by (unfold inj_on_def, blast) wenzelm@12258: paulson@13585: lemma inj_singleton: "inj (%s. {s})" paulson@13585: by (simp add: inj_on_def) paulson@13585: nipkow@15111: lemma inj_on_empty[iff]: "inj_on f {}" nipkow@15111: by(simp add: inj_on_def) nipkow@15111: nipkow@15303: lemma subset_inj_on: "[| inj_on f B; A <= B |] ==> inj_on f A" paulson@13585: by (unfold inj_on_def, blast) paulson@13585: nipkow@15111: lemma inj_on_Un: nipkow@15111: "inj_on f (A Un B) = nipkow@15111: (inj_on f A & inj_on f B & f`(A-B) Int f`(B-A) = {})" nipkow@15111: apply(unfold inj_on_def) nipkow@15111: apply (blast intro:sym) nipkow@15111: done nipkow@15111: nipkow@15111: lemma inj_on_insert[iff]: nipkow@15111: "inj_on f (insert a A) = (inj_on f A & f a ~: f`(A-{a}))" nipkow@15111: apply(unfold inj_on_def) nipkow@15111: apply (blast intro:sym) nipkow@15111: done nipkow@15111: nipkow@15111: lemma inj_on_diff: "inj_on f A ==> inj_on f (A-B)" nipkow@15111: apply(unfold inj_on_def) nipkow@15111: apply (blast) nipkow@15111: done nipkow@15111: hoelzl@40703: lemma comp_inj_on_iff: hoelzl@40703: "inj_on f A \ inj_on f' (f ` A) \ inj_on (f' o f) A" hoelzl@40703: by(auto simp add: comp_inj_on inj_on_def) hoelzl@40703: hoelzl@40703: lemma inj_on_imageI2: hoelzl@40703: "inj_on (f' o f) A \ inj_on f A" hoelzl@40703: by(auto simp add: comp_inj_on inj_on_def) hoelzl@40703: haftmann@51598: lemma inj_img_insertE: haftmann@51598: assumes "inj_on f A" haftmann@51598: assumes "x \ B" and "insert x B = f ` A" haftmann@51598: obtains x' A' where "x' \ A'" and "A = insert x' A'" blanchet@55019: and "x = f x'" and "B = f ` A'" haftmann@51598: proof - haftmann@51598: from assms have "x \ f ` A" by auto haftmann@51598: then obtain x' where *: "x' \ A" "x = f x'" by auto haftmann@51598: then have "A = insert x' (A - {x'})" by auto haftmann@51598: with assms * have "B = f ` (A - {x'})" haftmann@51598: by (auto dest: inj_on_contraD) haftmann@51598: have "x' \ A - {x'}" by simp wenzelm@60758: from \x' \ A - {x'}\ \A = insert x' (A - {x'})\ \x = f x'\ \B = image f (A - {x'})\ haftmann@51598: show ?thesis .. haftmann@51598: qed haftmann@51598: traytel@54578: lemma linorder_injI: traytel@54578: assumes hyp: "\x y. x < (y::'a::linorder) \ f x \ f y" traytel@54578: shows "inj f" wenzelm@61799: \ \Courtesy of Stephan Merz\ traytel@54578: proof (rule inj_onI) traytel@54578: fix x y traytel@54578: assume f_eq: "f x = f y" traytel@54578: show "x = y" by (rule linorder_cases) (auto dest: hyp simp: f_eq) traytel@54578: qed traytel@54578: hoelzl@40702: lemma surj_def: "surj f \ (\y. \x. y = f x)" hoelzl@40702: by auto hoelzl@39076: hoelzl@40702: lemma surjI: assumes *: "\ x. g (f x) = x" shows "surj g" hoelzl@40702: using *[symmetric] by auto paulson@13585: hoelzl@39076: lemma surjD: "surj f \ \x. y = f x" hoelzl@39076: by (simp add: surj_def) paulson@13585: hoelzl@39076: lemma surjE: "surj f \ (\x. y = f x \ C) \ C" hoelzl@39076: by (simp add: surj_def, blast) paulson@13585: paulson@13585: lemma comp_surj: "[| surj f; surj g |] ==> surj (g o f)" paulson@13585: apply (simp add: comp_def surj_def, clarify) paulson@13585: apply (drule_tac x = y in spec, clarify) paulson@13585: apply (drule_tac x = x in spec, blast) paulson@13585: done paulson@13585: ballarin@57282: lemma bij_betw_imageI: ballarin@57282: "\ inj_on f A; f ` A = B \ \ bij_betw f A B" ballarin@57282: unfolding bij_betw_def by clarify ballarin@57282: ballarin@57282: lemma bij_betw_imp_surj_on: "bij_betw f A B \ f ` A = B" ballarin@57282: unfolding bij_betw_def by clarify ballarin@57282: hoelzl@39074: lemma bij_betw_imp_surj: "bij_betw f A UNIV \ surj f" hoelzl@40702: unfolding bij_betw_def by auto hoelzl@39074: hoelzl@40703: lemma bij_betw_empty1: hoelzl@40703: assumes "bij_betw f {} A" hoelzl@40703: shows "A = {}" hoelzl@40703: using assms unfolding bij_betw_def by blast hoelzl@40703: hoelzl@40703: lemma bij_betw_empty2: hoelzl@40703: assumes "bij_betw f A {}" hoelzl@40703: shows "A = {}" hoelzl@40703: using assms unfolding bij_betw_def by blast hoelzl@40703: hoelzl@40703: lemma inj_on_imp_bij_betw: hoelzl@40703: "inj_on f A \ bij_betw f A (f ` A)" hoelzl@40703: unfolding bij_betw_def by simp hoelzl@40703: hoelzl@39076: lemma bij_def: "bij f \ inj f \ surj f" hoelzl@40702: unfolding bij_betw_def .. hoelzl@39074: paulson@13585: lemma bijI: "[| inj f; surj f |] ==> bij f" paulson@13585: by (simp add: bij_def) paulson@13585: paulson@13585: lemma bij_is_inj: "bij f ==> inj f" paulson@13585: by (simp add: bij_def) paulson@13585: paulson@13585: lemma bij_is_surj: "bij f ==> surj f" paulson@13585: by (simp add: bij_def) paulson@13585: nipkow@26105: lemma bij_betw_imp_inj_on: "bij_betw f A B \ inj_on f A" nipkow@26105: by (simp add: bij_betw_def) nipkow@26105: nipkow@31438: lemma bij_betw_trans: nipkow@31438: "bij_betw f A B \ bij_betw g B C \ bij_betw (g o f) A C" nipkow@31438: by(auto simp add:bij_betw_def comp_inj_on) nipkow@31438: hoelzl@40702: lemma bij_comp: "bij f \ bij g \ bij (g o f)" hoelzl@40702: by (rule bij_betw_trans) hoelzl@40702: hoelzl@40703: lemma bij_betw_comp_iff: hoelzl@40703: "bij_betw f A A' \ bij_betw f' A' A'' \ bij_betw (f' o f) A A''" hoelzl@40703: by(auto simp add: bij_betw_def inj_on_def) hoelzl@40703: hoelzl@40703: lemma bij_betw_comp_iff2: hoelzl@40703: assumes BIJ: "bij_betw f' A' A''" and IM: "f ` A \ A'" hoelzl@40703: shows "bij_betw f A A' \ bij_betw (f' o f) A A''" hoelzl@40703: using assms hoelzl@40703: proof(auto simp add: bij_betw_comp_iff) hoelzl@40703: assume *: "bij_betw (f' \ f) A A''" hoelzl@40703: thus "bij_betw f A A'" hoelzl@40703: using IM hoelzl@40703: proof(auto simp add: bij_betw_def) hoelzl@40703: assume "inj_on (f' \ f) A" hoelzl@40703: thus "inj_on f A" using inj_on_imageI2 by blast hoelzl@40703: next hoelzl@40703: fix a' assume **: "a' \ A'" hoelzl@40703: hence "f' a' \ A''" using BIJ unfolding bij_betw_def by auto hoelzl@40703: then obtain a where 1: "a \ A \ f'(f a) = f' a'" using * hoelzl@40703: unfolding bij_betw_def by force hoelzl@40703: hence "f a \ A'" using IM by auto hoelzl@40703: hence "f a = a'" using BIJ ** 1 unfolding bij_betw_def inj_on_def by auto hoelzl@40703: thus "a' \ f ` A" using 1 by auto hoelzl@40703: qed hoelzl@40703: qed hoelzl@40703: nipkow@26105: lemma bij_betw_inv: assumes "bij_betw f A B" shows "EX g. bij_betw g B A" nipkow@26105: proof - nipkow@26105: have i: "inj_on f A" and s: "f ` A = B" nipkow@26105: using assms by(auto simp:bij_betw_def) nipkow@26105: let ?P = "%b a. a:A \ f a = b" let ?g = "%b. The (?P b)" nipkow@26105: { fix a b assume P: "?P b a" haftmann@56077: hence ex1: "\a. ?P b a" using s by blast nipkow@26105: hence uex1: "\!a. ?P b a" by(blast dest:inj_onD[OF i]) nipkow@26105: hence " ?g b = a" using the1_equality[OF uex1, OF P] P by simp nipkow@26105: } note g = this nipkow@26105: have "inj_on ?g B" nipkow@26105: proof(rule inj_onI) nipkow@26105: fix x y assume "x:B" "y:B" "?g x = ?g y" wenzelm@60758: from s \x:B\ obtain a1 where a1: "?P x a1" by blast wenzelm@60758: from s \y:B\ obtain a2 where a2: "?P y a2" by blast wenzelm@60758: from g[OF a1] a1 g[OF a2] a2 \?g x = ?g y\ show "x=y" by simp nipkow@26105: qed nipkow@26105: moreover have "?g ` B = A" haftmann@56077: proof(auto simp: image_def) nipkow@26105: fix b assume "b:B" haftmann@56077: with s obtain a where P: "?P b a" by blast nipkow@26105: thus "?g b \ A" using g[OF P] by auto nipkow@26105: next nipkow@26105: fix a assume "a:A" haftmann@56077: then obtain b where P: "?P b a" using s by blast haftmann@56077: then have "b:B" using s by blast nipkow@26105: with g[OF P] show "\b\B. a = ?g b" by blast nipkow@26105: qed nipkow@26105: ultimately show ?thesis by(auto simp:bij_betw_def) nipkow@26105: qed nipkow@26105: hoelzl@40703: lemma bij_betw_cong: hoelzl@40703: "(\ a. a \ A \ f a = g a) \ bij_betw f A A' = bij_betw g A A'" hoelzl@40703: unfolding bij_betw_def inj_on_def by force hoelzl@40703: hoelzl@40703: lemma bij_betw_id[intro, simp]: hoelzl@40703: "bij_betw id A A" hoelzl@40703: unfolding bij_betw_def id_def by auto hoelzl@40703: hoelzl@40703: lemma bij_betw_id_iff: hoelzl@40703: "bij_betw id A B \ A = B" hoelzl@40703: by(auto simp add: bij_betw_def) hoelzl@40703: hoelzl@39075: lemma bij_betw_combine: hoelzl@39075: assumes "bij_betw f A B" "bij_betw f C D" "B \ D = {}" hoelzl@39075: shows "bij_betw f (A \ C) (B \ D)" hoelzl@39075: using assms unfolding bij_betw_def inj_on_Un image_Un by auto hoelzl@39075: hoelzl@40703: lemma bij_betw_subset: hoelzl@40703: assumes BIJ: "bij_betw f A A'" and hoelzl@40703: SUB: "B \ A" and IM: "f ` B = B'" hoelzl@40703: shows "bij_betw f B B'" hoelzl@40703: using assms hoelzl@40703: by(unfold bij_betw_def inj_on_def, auto simp add: inj_on_def) hoelzl@40703: haftmann@58195: lemma bij_pointE: haftmann@58195: assumes "bij f" haftmann@58195: obtains x where "y = f x" and "\x'. y = f x' \ x' = x" haftmann@58195: proof - haftmann@58195: from assms have "inj f" by (rule bij_is_inj) haftmann@58195: moreover from assms have "surj f" by (rule bij_is_surj) haftmann@58195: then have "y \ range f" by simp haftmann@58195: ultimately have "\!x. y = f x" by (simp add: range_ex1_eq) haftmann@58195: with that show thesis by blast haftmann@58195: qed haftmann@58195: paulson@13585: lemma surj_image_vimage_eq: "surj f ==> f ` (f -` A) = A" hoelzl@40702: by simp paulson@13585: hoelzl@42903: lemma surj_vimage_empty: hoelzl@42903: assumes "surj f" shows "f -` A = {} \ A = {}" wenzelm@60758: using surj_image_vimage_eq[OF \surj f\, of A] nipkow@44890: by (intro iffI) fastforce+ hoelzl@42903: paulson@13585: lemma inj_vimage_image_eq: "inj f ==> f -` (f ` A) = A" paulson@13585: by (simp add: inj_on_def, blast) paulson@13585: paulson@13585: lemma vimage_subsetD: "surj f ==> f -` B <= A ==> B <= f ` A" hoelzl@40702: by (blast intro: sym) paulson@13585: paulson@13585: lemma vimage_subsetI: "inj f ==> B <= f ` A ==> f -` B <= A" paulson@13585: by (unfold inj_on_def, blast) paulson@13585: paulson@13585: lemma vimage_subset_eq: "bij f ==> (f -` B <= A) = (B <= f ` A)" paulson@13585: apply (unfold bij_def) paulson@13585: apply (blast del: subsetI intro: vimage_subsetI vimage_subsetD) paulson@13585: done paulson@13585: Andreas@53927: lemma inj_on_image_eq_iff: "\ inj_on f C; A \ C; B \ C \ \ f ` A = f ` B \ A = B" Andreas@53927: by(fastforce simp add: inj_on_def) Andreas@53927: nipkow@31438: lemma inj_on_Un_image_eq_iff: "inj_on f (A \ B) \ f ` A = f ` B \ A = B" Andreas@53927: by(erule inj_on_image_eq_iff) simp_all nipkow@31438: paulson@13585: lemma inj_on_image_Int: paulson@13585: "[| inj_on f C; A<=C; B<=C |] ==> f`(A Int B) = f`A Int f`B" paulson@60303: by (simp add: inj_on_def, blast) paulson@13585: paulson@13585: lemma inj_on_image_set_diff: paulson@60303: "[| inj_on f C; A-B \ C; B \ C |] ==> f`(A-B) = f`A - f`B" paulson@60303: by (simp add: inj_on_def, blast) paulson@13585: paulson@13585: lemma image_Int: "inj f ==> f`(A Int B) = f`A Int f`B" paulson@60303: by (simp add: inj_on_def, blast) paulson@13585: paulson@13585: lemma image_set_diff: "inj f ==> f`(A-B) = f`A - f`B" paulson@13585: by (simp add: inj_on_def, blast) paulson@13585: lp15@59504: lemma inj_on_image_mem_iff: "\inj_on f B; a \ B; A \ B\ \ f a \ f`A \ a \ A" lp15@59504: by (auto simp: inj_on_def) lp15@59504: lp15@61520: (*FIXME DELETE*) lp15@61520: lemma inj_on_image_mem_iff_alt: "inj_on f B \ A \ B \ f a \ f`A \ a \ B \ a \ A" lp15@61520: by (blast dest: inj_onD) lp15@61520: lp15@59504: lemma inj_image_mem_iff: "inj f \ f a \ f`A \ a \ A" lp15@59504: by (blast dest: injD) paulson@13585: paulson@13585: lemma inj_image_subset_iff: "inj f ==> (f`A <= f`B) = (A<=B)" lp15@59504: by (blast dest: injD) paulson@13585: paulson@13585: lemma inj_image_eq_iff: "inj f ==> (f`A = f`B) = (A = B)" lp15@59504: by (blast dest: injD) paulson@13585: paulson@13585: lemma surj_Compl_image_subset: "surj f ==> -(f`A) <= f`(-A)" hoelzl@40702: by auto paulson@13585: paulson@13585: lemma inj_image_Compl_subset: "inj f ==> f`(-A) <= -(f`A)" paulson@13585: by (auto simp add: inj_on_def) paulson@5852: paulson@13585: lemma bij_image_Compl_eq: "bij f ==> f`(-A) = -(f`A)" paulson@13585: apply (simp add: bij_def) paulson@13585: apply (rule equalityI) paulson@13585: apply (simp_all (no_asm_simp) add: inj_image_Compl_subset surj_Compl_image_subset) paulson@13585: done paulson@13585: haftmann@41657: lemma inj_vimage_singleton: "inj f \ f -` {a} \ {THE x. f x = a}" wenzelm@61799: \ \The inverse image of a singleton under an injective function wenzelm@60758: is included in a singleton.\ haftmann@41657: apply (auto simp add: inj_on_def) haftmann@41657: apply (blast intro: the_equality [symmetric]) haftmann@41657: done haftmann@41657: hoelzl@43991: lemma inj_on_vimage_singleton: hoelzl@43991: "inj_on f A \ f -` {a} \ A \ {THE x. x \ A \ f x = a}" hoelzl@43991: by (auto simp add: inj_on_def intro: the_equality [symmetric]) hoelzl@43991: hoelzl@35584: lemma (in ordered_ab_group_add) inj_uminus[simp, intro]: "inj_on uminus A" hoelzl@35580: by (auto intro!: inj_onI) paulson@13585: hoelzl@35584: lemma (in linorder) strict_mono_imp_inj_on: "strict_mono f \ inj_on f A" hoelzl@35584: by (auto intro!: inj_onI dest: strict_mono_eq) hoelzl@35584: blanchet@55019: lemma bij_betw_byWitness: blanchet@55019: assumes LEFT: "\a \ A. f'(f a) = a" and blanchet@55019: RIGHT: "\a' \ A'. f(f' a') = a'" and blanchet@55019: IM1: "f ` A \ A'" and IM2: "f' ` A' \ A" blanchet@55019: shows "bij_betw f A A'" blanchet@55019: using assms blanchet@55019: proof(unfold bij_betw_def inj_on_def, safe) blanchet@55019: fix a b assume *: "a \ A" "b \ A" and **: "f a = f b" blanchet@55019: have "a = f'(f a) \ b = f'(f b)" using * LEFT by simp blanchet@55019: with ** show "a = b" by simp blanchet@55019: next blanchet@55019: fix a' assume *: "a' \ A'" blanchet@55019: hence "f' a' \ A" using IM2 by blast blanchet@55019: moreover blanchet@55019: have "a' = f(f' a')" using * RIGHT by simp blanchet@55019: ultimately show "a' \ f ` A" by blast blanchet@55019: qed blanchet@55019: blanchet@55019: corollary notIn_Un_bij_betw: blanchet@55019: assumes NIN: "b \ A" and NIN': "f b \ A'" and blanchet@55019: BIJ: "bij_betw f A A'" blanchet@55019: shows "bij_betw f (A \ {b}) (A' \ {f b})" blanchet@55019: proof- blanchet@55019: have "bij_betw f {b} {f b}" blanchet@55019: unfolding bij_betw_def inj_on_def by simp blanchet@55019: with assms show ?thesis blanchet@55019: using bij_betw_combine[of f A A' "{b}" "{f b}"] by blast blanchet@55019: qed blanchet@55019: blanchet@55019: lemma notIn_Un_bij_betw3: blanchet@55019: assumes NIN: "b \ A" and NIN': "f b \ A'" blanchet@55019: shows "bij_betw f A A' = bij_betw f (A \ {b}) (A' \ {f b})" blanchet@55019: proof blanchet@55019: assume "bij_betw f A A'" blanchet@55019: thus "bij_betw f (A \ {b}) (A' \ {f b})" blanchet@55019: using assms notIn_Un_bij_betw[of b A f A'] by blast blanchet@55019: next blanchet@55019: assume *: "bij_betw f (A \ {b}) (A' \ {f b})" blanchet@55019: have "f ` A = A'" blanchet@55019: proof(auto) blanchet@55019: fix a assume **: "a \ A" blanchet@55019: hence "f a \ A' \ {f b}" using * unfolding bij_betw_def by blast blanchet@55019: moreover blanchet@55019: {assume "f a = f b" blanchet@55019: hence "a = b" using * ** unfolding bij_betw_def inj_on_def by blast blanchet@55019: with NIN ** have False by blast blanchet@55019: } blanchet@55019: ultimately show "f a \ A'" by blast blanchet@55019: next blanchet@55019: fix a' assume **: "a' \ A'" blanchet@55019: hence "a' \ f`(A \ {b})" blanchet@55019: using * by (auto simp add: bij_betw_def) blanchet@55019: then obtain a where 1: "a \ A \ {b} \ f a = a'" by blast blanchet@55019: moreover blanchet@55019: {assume "a = b" with 1 ** NIN' have False by blast blanchet@55019: } blanchet@55019: ultimately have "a \ A" by blast blanchet@55019: with 1 show "a' \ f ` A" by blast blanchet@55019: qed blanchet@55019: thus "bij_betw f A A'" using * bij_betw_subset[of f "A \ {b}" _ A] by blast blanchet@55019: qed blanchet@55019: haftmann@41657: wenzelm@60758: subsection\Function Updating\ paulson@13585: haftmann@44277: definition fun_upd :: "('a => 'b) => 'a => 'b => ('a => 'b)" where haftmann@26147: "fun_upd f a b == % x. if x=a then b else f x" haftmann@26147: wenzelm@41229: nonterminal updbinds and updbind wenzelm@41229: haftmann@26147: syntax haftmann@26147: "_updbind" :: "['a, 'a] => updbind" ("(2_ :=/ _)") haftmann@26147: "" :: "updbind => updbinds" ("_") haftmann@26147: "_updbinds":: "[updbind, updbinds] => updbinds" ("_,/ _") wenzelm@35115: "_Update" :: "['a, updbinds] => 'a" ("_/'((_)')" [1000, 0] 900) haftmann@26147: haftmann@26147: translations wenzelm@35115: "_Update f (_updbinds b bs)" == "_Update (_Update f b) bs" wenzelm@35115: "f(x:=y)" == "CONST fun_upd f x y" haftmann@26147: blanchet@55414: (* Hint: to define the sum of two functions (or maps), use case_sum. blanchet@58111: A nice infix syntax could be defined by wenzelm@35115: notation blanchet@55414: case_sum (infixr "'(+')"80) haftmann@26147: *) haftmann@26147: paulson@13585: lemma fun_upd_idem_iff: "(f(x:=y) = f) = (f x = y)" paulson@13585: apply (simp add: fun_upd_def, safe) paulson@13585: apply (erule subst) paulson@13585: apply (rule_tac [2] ext, auto) paulson@13585: done paulson@13585: wenzelm@45603: lemma fun_upd_idem: "f x = y ==> f(x:=y) = f" wenzelm@45603: by (simp only: fun_upd_idem_iff) paulson@13585: wenzelm@45603: lemma fun_upd_triv [iff]: "f(x := f x) = f" wenzelm@45603: by (simp only: fun_upd_idem) paulson@13585: paulson@13585: lemma fun_upd_apply [simp]: "(f(x:=y))z = (if z=x then y else f z)" paulson@17084: by (simp add: fun_upd_def) paulson@13585: paulson@13585: (* fun_upd_apply supersedes these two, but they are useful paulson@13585: if fun_upd_apply is intentionally removed from the simpset *) paulson@13585: lemma fun_upd_same: "(f(x:=y)) x = y" paulson@13585: by simp paulson@13585: paulson@13585: lemma fun_upd_other: "z~=x ==> (f(x:=y)) z = f z" paulson@13585: by simp paulson@13585: paulson@13585: lemma fun_upd_upd [simp]: "f(x:=y,x:=z) = f(x:=z)" nipkow@39302: by (simp add: fun_eq_iff) paulson@13585: paulson@13585: lemma fun_upd_twist: "a ~= c ==> (m(a:=b))(c:=d) = (m(c:=d))(a:=b)" paulson@13585: by (rule ext, auto) paulson@13585: haftmann@56077: lemma inj_on_fun_updI: haftmann@56077: "inj_on f A \ y \ f ` A \ inj_on (f(x := y)) A" haftmann@56077: by (fastforce simp: inj_on_def) nipkow@15303: paulson@15510: lemma fun_upd_image: paulson@15510: "f(x:=y) ` A = (if x \ A then insert y (f ` (A-{x})) else f ` A)" paulson@15510: by auto paulson@15510: nipkow@31080: lemma fun_upd_comp: "f \ (g(x := y)) = (f \ g)(x := f y)" huffman@44921: by auto nipkow@31080: Andreas@61630: lemma fun_upd_eqD: "f(x := y) = g(x := z) \ y = z" Andreas@61630: by(simp add: fun_eq_iff split: split_if_asm) haftmann@26147: wenzelm@61799: subsection \\override_on\\ haftmann@26147: haftmann@44277: definition override_on :: "('a \ 'b) \ ('a \ 'b) \ 'a set \ 'a \ 'b" where haftmann@26147: "override_on f g A = (\a. if a \ A then g a else f a)" nipkow@13910: nipkow@15691: lemma override_on_emptyset[simp]: "override_on f g {} = f" nipkow@15691: by(simp add:override_on_def) nipkow@13910: nipkow@15691: lemma override_on_apply_notin[simp]: "a ~: A ==> (override_on f g A) a = f a" nipkow@15691: by(simp add:override_on_def) nipkow@13910: nipkow@15691: lemma override_on_apply_in[simp]: "a : A ==> (override_on f g A) a = g a" nipkow@15691: by(simp add:override_on_def) nipkow@13910: haftmann@26147: wenzelm@61799: subsection \\swap\\ paulson@15510: haftmann@56608: definition swap :: "'a \ 'a \ ('a \ 'b) \ ('a \ 'b)" haftmann@56608: where haftmann@22744: "swap a b f = f (a := f b, b:= f a)" paulson@15510: haftmann@56608: lemma swap_apply [simp]: haftmann@56608: "swap a b f a = f b" haftmann@56608: "swap a b f b = f a" haftmann@56608: "c \ a \ c \ b \ swap a b f c = f c" haftmann@56608: by (simp_all add: swap_def) haftmann@56608: haftmann@56608: lemma swap_self [simp]: haftmann@56608: "swap a a f = f" haftmann@56608: by (simp add: swap_def) paulson@15510: haftmann@56608: lemma swap_commute: haftmann@56608: "swap a b f = swap b a f" haftmann@56608: by (simp add: fun_upd_def swap_def fun_eq_iff) paulson@15510: haftmann@56608: lemma swap_nilpotent [simp]: haftmann@56608: "swap a b (swap a b f) = f" haftmann@56608: by (rule ext, simp add: fun_upd_def swap_def) haftmann@56608: haftmann@56608: lemma swap_comp_involutory [simp]: haftmann@56608: "swap a b \ swap a b = id" haftmann@56608: by (rule ext) simp paulson@15510: huffman@34145: lemma swap_triple: huffman@34145: assumes "a \ c" and "b \ c" huffman@34145: shows "swap a b (swap b c (swap a b f)) = swap a c f" nipkow@39302: using assms by (simp add: fun_eq_iff swap_def) huffman@34145: huffman@34101: lemma comp_swap: "f \ swap a b g = swap a b (f \ g)" haftmann@56608: by (rule ext, simp add: fun_upd_def swap_def) huffman@34101: hoelzl@39076: lemma swap_image_eq [simp]: hoelzl@39076: assumes "a \ A" "b \ A" shows "swap a b f ` A = f ` A" hoelzl@39076: proof - hoelzl@39076: have subset: "\f. swap a b f ` A \ f ` A" hoelzl@39076: using assms by (auto simp: image_iff swap_def) hoelzl@39076: then have "swap a b (swap a b f) ` A \ (swap a b f) ` A" . hoelzl@39076: with subset[of f] show ?thesis by auto hoelzl@39076: qed hoelzl@39076: paulson@15510: lemma inj_on_imp_inj_on_swap: hoelzl@39076: "\inj_on f A; a \ A; b \ A\ \ inj_on (swap a b f) A" hoelzl@39076: by (simp add: inj_on_def swap_def, blast) paulson@15510: paulson@15510: lemma inj_on_swap_iff [simp]: hoelzl@39076: assumes A: "a \ A" "b \ A" shows "inj_on (swap a b f) A \ inj_on f A" hoelzl@39075: proof paulson@15510: assume "inj_on (swap a b f) A" hoelzl@39075: with A have "inj_on (swap a b (swap a b f)) A" hoelzl@39075: by (iprover intro: inj_on_imp_inj_on_swap) hoelzl@39075: thus "inj_on f A" by simp paulson@15510: next paulson@15510: assume "inj_on f A" krauss@34209: with A show "inj_on (swap a b f) A" by (iprover intro: inj_on_imp_inj_on_swap) paulson@15510: qed paulson@15510: hoelzl@39076: lemma surj_imp_surj_swap: "surj f \ surj (swap a b f)" hoelzl@40702: by simp paulson@15510: hoelzl@39076: lemma surj_swap_iff [simp]: "surj (swap a b f) \ surj f" hoelzl@40702: by simp haftmann@21547: hoelzl@39076: lemma bij_betw_swap_iff [simp]: hoelzl@39076: "\ x \ A; y \ A \ \ bij_betw (swap x y f) A B \ bij_betw f A B" hoelzl@39076: by (auto simp: bij_betw_def) hoelzl@39076: hoelzl@39076: lemma bij_swap_iff [simp]: "bij (swap a b f) \ bij f" hoelzl@39076: by simp hoelzl@39075: wenzelm@36176: hide_const (open) swap haftmann@21547: haftmann@56608: wenzelm@60758: subsection \Inversion of injective functions\ haftmann@31949: nipkow@33057: definition the_inv_into :: "'a set => ('a => 'b) => ('b => 'a)" where haftmann@44277: "the_inv_into A f == %x. THE y. y : A & f y = x" nipkow@32961: nipkow@33057: lemma the_inv_into_f_f: nipkow@33057: "[| inj_on f A; x : A |] ==> the_inv_into A f (f x) = x" nipkow@33057: apply (simp add: the_inv_into_def inj_on_def) krauss@34209: apply blast nipkow@32961: done nipkow@32961: nipkow@33057: lemma f_the_inv_into_f: nipkow@33057: "inj_on f A ==> y : f`A ==> f (the_inv_into A f y) = y" nipkow@33057: apply (simp add: the_inv_into_def) nipkow@32961: apply (rule the1I2) nipkow@32961: apply(blast dest: inj_onD) nipkow@32961: apply blast nipkow@32961: done nipkow@32961: nipkow@33057: lemma the_inv_into_into: nipkow@33057: "[| inj_on f A; x : f ` A; A <= B |] ==> the_inv_into A f x : B" nipkow@33057: apply (simp add: the_inv_into_def) nipkow@32961: apply (rule the1I2) nipkow@32961: apply(blast dest: inj_onD) nipkow@32961: apply blast nipkow@32961: done nipkow@32961: nipkow@33057: lemma the_inv_into_onto[simp]: nipkow@33057: "inj_on f A ==> the_inv_into A f ` (f ` A) = A" nipkow@33057: by (fast intro:the_inv_into_into the_inv_into_f_f[symmetric]) nipkow@32961: nipkow@33057: lemma the_inv_into_f_eq: nipkow@33057: "[| inj_on f A; f x = y; x : A |] ==> the_inv_into A f y = x" nipkow@32961: apply (erule subst) nipkow@33057: apply (erule the_inv_into_f_f, assumption) nipkow@32961: done nipkow@32961: nipkow@33057: lemma the_inv_into_comp: nipkow@32961: "[| inj_on f (g ` A); inj_on g A; x : f ` g ` A |] ==> nipkow@33057: the_inv_into A (f o g) x = (the_inv_into A g o the_inv_into (g ` A) f) x" nipkow@33057: apply (rule the_inv_into_f_eq) nipkow@32961: apply (fast intro: comp_inj_on) nipkow@33057: apply (simp add: f_the_inv_into_f the_inv_into_into) nipkow@33057: apply (simp add: the_inv_into_into) nipkow@32961: done nipkow@32961: nipkow@33057: lemma inj_on_the_inv_into: nipkow@33057: "inj_on f A \ inj_on (the_inv_into A f) (f ` A)" haftmann@56077: by (auto intro: inj_onI simp: the_inv_into_f_f) nipkow@32961: nipkow@33057: lemma bij_betw_the_inv_into: nipkow@33057: "bij_betw f A B \ bij_betw (the_inv_into A f) B A" nipkow@33057: by (auto simp add: bij_betw_def inj_on_the_inv_into the_inv_into_into) nipkow@32961: berghofe@32998: abbreviation the_inv :: "('a \ 'b) \ ('b \ 'a)" where nipkow@33057: "the_inv f \ the_inv_into UNIV f" berghofe@32998: berghofe@32998: lemma the_inv_f_f: berghofe@32998: assumes "inj f" berghofe@32998: shows "the_inv f (f x) = x" using assms UNIV_I nipkow@33057: by (rule the_inv_into_f_f) berghofe@32998: haftmann@44277: wenzelm@60758: subsection \Cantor's Paradox\ hoelzl@40703: blanchet@54147: lemma Cantors_paradox: hoelzl@40703: "\(\f. f ` A = Pow A)" hoelzl@40703: proof clarify hoelzl@40703: fix f assume "f ` A = Pow A" hence *: "Pow A \ f ` A" by blast hoelzl@40703: let ?X = "{a \ A. a \ f a}" hoelzl@40703: have "?X \ Pow A" unfolding Pow_def by auto hoelzl@40703: with * obtain x where "x \ A \ f x = ?X" by blast hoelzl@40703: thus False by best hoelzl@40703: qed haftmann@31949: paulson@61204: subsection \Setup\ haftmann@40969: wenzelm@60758: subsubsection \Proof tools\ haftmann@22845: wenzelm@60758: text \simplifies terms of the form wenzelm@60758: f(...,x:=y,...,x:=z,...) to f(...,x:=z,...)\ haftmann@22845: wenzelm@60758: simproc_setup fun_upd2 ("f(v := w, x := y)") = \fn _ => haftmann@22845: let haftmann@22845: fun gen_fun_upd NONE T _ _ = NONE wenzelm@24017: | gen_fun_upd (SOME f) T x y = SOME (Const (@{const_name fun_upd}, T) $ f $ x $ y) haftmann@22845: fun dest_fun_T1 (Type (_, T :: Ts)) = T haftmann@22845: fun find_double (t as Const (@{const_name fun_upd},T) $ f $ x $ y) = haftmann@22845: let haftmann@22845: fun find (Const (@{const_name fun_upd},T) $ g $ v $ w) = haftmann@22845: if v aconv x then SOME g else gen_fun_upd (find g) T v w haftmann@22845: | find t = NONE haftmann@22845: in (dest_fun_T1 T, gen_fun_upd (find f) T x y) end wenzelm@24017: wenzelm@51717: val ss = simpset_of @{context} wenzelm@51717: wenzelm@51717: fun proc ctxt ct = wenzelm@24017: let wenzelm@24017: val t = Thm.term_of ct wenzelm@24017: in wenzelm@24017: case find_double t of wenzelm@24017: (T, NONE) => NONE wenzelm@24017: | (T, SOME rhs) => wenzelm@27330: SOME (Goal.prove ctxt [] [] (Logic.mk_equals (t, rhs)) wenzelm@24017: (fn _ => wenzelm@59498: resolve_tac ctxt [eq_reflection] 1 THEN wenzelm@59498: resolve_tac ctxt @{thms ext} 1 THEN wenzelm@51717: simp_tac (put_simpset ss ctxt) 1)) wenzelm@24017: end wenzelm@24017: in proc end wenzelm@60758: \ haftmann@22845: haftmann@22845: wenzelm@60758: subsubsection \Functorial structure of types\ haftmann@40969: blanchet@55467: ML_file "Tools/functor.ML" haftmann@40969: blanchet@55467: functor map_fun: map_fun haftmann@47488: by (simp_all add: fun_eq_iff) haftmann@47488: blanchet@55467: functor vimage haftmann@49739: by (simp_all add: fun_eq_iff vimage_comp) haftmann@49739: wenzelm@60758: text \Legacy theorem names\ haftmann@49739: haftmann@49739: lemmas o_def = comp_def haftmann@49739: lemmas o_apply = comp_apply haftmann@49739: lemmas o_assoc = comp_assoc [symmetric] haftmann@49739: lemmas id_o = id_comp haftmann@49739: lemmas o_id = comp_id haftmann@49739: lemmas o_eq_dest = comp_eq_dest haftmann@49739: lemmas o_eq_elim = comp_eq_elim blanchet@55066: lemmas o_eq_dest_lhs = comp_eq_dest_lhs blanchet@55066: lemmas o_eq_id_dest = comp_eq_id_dest haftmann@47488: nipkow@2912: end haftmann@56015: