kuncar@47308: (* Title: HOL/Lifting.thy kuncar@47308: Author: Brian Huffman and Ondrej Kuncar kuncar@47308: Author: Cezary Kaliszyk and Christian Urban kuncar@47308: *) kuncar@47308: kuncar@47308: header {* Lifting package *} kuncar@47308: kuncar@47308: theory Lifting haftmann@51112: imports Equiv_Relations Transfer kuncar@47308: keywords kuncar@51374: "parametric" and kuncar@53219: "print_quot_maps" "print_quotients" :: diag and kuncar@47308: "lift_definition" :: thy_goal and kuncar@53651: "setup_lifting" "lifting_forget" "lifting_update" :: thy_decl kuncar@47308: begin kuncar@47308: huffman@47325: subsection {* Function map *} kuncar@47308: kuncar@53011: context kuncar@53011: begin kuncar@53011: interpretation lifting_syntax . kuncar@47308: kuncar@47308: lemma map_fun_id: kuncar@47308: "(id ---> id) = id" kuncar@47308: by (simp add: fun_eq_iff) kuncar@47308: kuncar@51994: subsection {* Other predicates on relations *} kuncar@51994: kuncar@51994: definition left_total :: "('a \ 'b \ bool) \ bool" kuncar@51994: where "left_total R \ (\x. \y. R x y)" kuncar@51994: kuncar@51994: lemma left_totalI: kuncar@51994: "(\x. \y. R x y) \ left_total R" kuncar@51994: unfolding left_total_def by blast kuncar@51994: kuncar@51994: lemma left_totalE: kuncar@51994: assumes "left_total R" kuncar@51994: obtains "(\x. \y. R x y)" kuncar@51994: using assms unfolding left_total_def by blast kuncar@51994: kuncar@53952: lemma bi_total_iff: "bi_total A = (right_total A \ left_total A)" kuncar@53952: unfolding left_total_def right_total_def bi_total_def by blast kuncar@53952: Andreas@53927: lemma bi_total_conv_left_right: "bi_total R \ left_total R \ right_total R" Andreas@53927: by(simp add: left_total_def right_total_def bi_total_def) Andreas@53927: kuncar@51994: definition left_unique :: "('a \ 'b \ bool) \ bool" kuncar@51994: where "left_unique R \ (\x y z. R x z \ R y z \ x = y)" kuncar@51994: kuncar@53952: lemma left_unique_transfer [transfer_rule]: kuncar@53952: assumes [transfer_rule]: "right_total A" kuncar@53952: assumes [transfer_rule]: "right_total B" kuncar@53952: assumes [transfer_rule]: "bi_unique A" kuncar@53952: shows "((A ===> B ===> op=) ===> implies) left_unique left_unique" kuncar@53952: using assms unfolding left_unique_def[abs_def] right_total_def bi_unique_def fun_rel_def kuncar@53952: by metis kuncar@53952: kuncar@53952: lemma bi_unique_iff: "bi_unique A = (right_unique A \ left_unique A)" kuncar@53952: unfolding left_unique_def right_unique_def bi_unique_def by blast kuncar@53952: Andreas@53927: lemma bi_unique_conv_left_right: "bi_unique R \ left_unique R \ right_unique R" Andreas@53927: by(auto simp add: left_unique_def right_unique_def bi_unique_def) Andreas@53927: Andreas@53927: lemma left_uniqueI: "(\x y z. \ A x z; A y z \ \ x = y) \ left_unique A" Andreas@53927: unfolding left_unique_def by blast Andreas@53927: Andreas@53927: lemma left_uniqueD: "\ left_unique A; A x z; A y z \ \ x = y" Andreas@53927: unfolding left_unique_def by blast Andreas@53927: kuncar@52036: lemma left_total_fun: kuncar@52036: "\left_unique A; left_total B\ \ left_total (A ===> B)" kuncar@52036: unfolding left_total_def fun_rel_def kuncar@52036: apply (rule allI, rename_tac f) kuncar@52036: apply (rule_tac x="\y. SOME z. B (f (THE x. A x y)) z" in exI) kuncar@52036: apply clarify kuncar@52036: apply (subgoal_tac "(THE x. A x y) = x", simp) kuncar@52036: apply (rule someI_ex) kuncar@52036: apply (simp) kuncar@52036: apply (rule the_equality) kuncar@52036: apply assumption kuncar@52036: apply (simp add: left_unique_def) kuncar@52036: done kuncar@52036: kuncar@52036: lemma left_unique_fun: kuncar@52036: "\left_total A; left_unique B\ \ left_unique (A ===> B)" kuncar@52036: unfolding left_total_def left_unique_def fun_rel_def kuncar@52036: by (clarify, rule ext, fast) kuncar@52036: kuncar@52036: lemma left_total_eq: "left_total op=" unfolding left_total_def by blast kuncar@52036: kuncar@52036: lemma left_unique_eq: "left_unique op=" unfolding left_unique_def by blast kuncar@52036: Andreas@53944: lemma [simp]: Andreas@53944: shows left_unique_conversep: "left_unique A\\ \ right_unique A" Andreas@53944: and right_unique_conversep: "right_unique A\\ \ left_unique A" Andreas@53944: by(auto simp add: left_unique_def right_unique_def) Andreas@53944: Andreas@53944: lemma [simp]: Andreas@53944: shows left_total_conversep: "left_total A\\ \ right_total A" Andreas@53944: and right_total_conversep: "right_total A\\ \ left_total A" Andreas@53944: by(simp_all add: left_total_def right_total_def) Andreas@53944: kuncar@47308: subsection {* Quotient Predicate *} kuncar@47308: kuncar@47308: definition kuncar@47308: "Quotient R Abs Rep T \ kuncar@47308: (\a. Abs (Rep a) = a) \ kuncar@47308: (\a. R (Rep a) (Rep a)) \ kuncar@47308: (\r s. R r s \ R r r \ R s s \ Abs r = Abs s) \ kuncar@47308: T = (\x y. R x x \ Abs x = y)" kuncar@47308: kuncar@47308: lemma QuotientI: kuncar@47308: assumes "\a. Abs (Rep a) = a" kuncar@47308: and "\a. R (Rep a) (Rep a)" kuncar@47308: and "\r s. R r s \ R r r \ R s s \ Abs r = Abs s" kuncar@47308: and "T = (\x y. R x x \ Abs x = y)" kuncar@47308: shows "Quotient R Abs Rep T" kuncar@47308: using assms unfolding Quotient_def by blast kuncar@47308: huffman@47536: context huffman@47536: fixes R Abs Rep T kuncar@47308: assumes a: "Quotient R Abs Rep T" huffman@47536: begin huffman@47536: huffman@47536: lemma Quotient_abs_rep: "Abs (Rep a) = a" huffman@47536: using a unfolding Quotient_def kuncar@47308: by simp kuncar@47308: huffman@47536: lemma Quotient_rep_reflp: "R (Rep a) (Rep a)" huffman@47536: using a unfolding Quotient_def kuncar@47308: by blast kuncar@47308: kuncar@47308: lemma Quotient_rel: huffman@47536: "R r r \ R s s \ Abs r = Abs s \ R r s" -- {* orientation does not loop on rewriting *} huffman@47536: using a unfolding Quotient_def kuncar@47308: by blast kuncar@47308: huffman@47536: lemma Quotient_cr_rel: "T = (\x y. R x x \ Abs x = y)" kuncar@47308: using a unfolding Quotient_def kuncar@47308: by blast kuncar@47308: huffman@47536: lemma Quotient_refl1: "R r s \ R r r" huffman@47536: using a unfolding Quotient_def huffman@47536: by fast huffman@47536: huffman@47536: lemma Quotient_refl2: "R r s \ R s s" huffman@47536: using a unfolding Quotient_def huffman@47536: by fast huffman@47536: huffman@47536: lemma Quotient_rel_rep: "R (Rep a) (Rep b) \ a = b" huffman@47536: using a unfolding Quotient_def huffman@47536: by metis huffman@47536: huffman@47536: lemma Quotient_rep_abs: "R r r \ R (Rep (Abs r)) r" kuncar@47308: using a unfolding Quotient_def kuncar@47308: by blast kuncar@47308: kuncar@47937: lemma Quotient_rep_abs_fold_unmap: kuncar@47937: assumes "x' \ Abs x" and "R x x" and "Rep x' \ Rep' x'" kuncar@47937: shows "R (Rep' x') x" kuncar@47937: proof - kuncar@47937: have "R (Rep x') x" using assms(1-2) Quotient_rep_abs by auto kuncar@47937: then show ?thesis using assms(3) by simp kuncar@47937: qed kuncar@47937: kuncar@47937: lemma Quotient_Rep_eq: kuncar@47937: assumes "x' \ Abs x" kuncar@47937: shows "Rep x' \ Rep x'" kuncar@47937: by simp kuncar@47937: huffman@47536: lemma Quotient_rel_abs: "R r s \ Abs r = Abs s" huffman@47536: using a unfolding Quotient_def huffman@47536: by blast huffman@47536: kuncar@47937: lemma Quotient_rel_abs2: kuncar@47937: assumes "R (Rep x) y" kuncar@47937: shows "x = Abs y" kuncar@47937: proof - kuncar@47937: from assms have "Abs (Rep x) = Abs y" by (auto intro: Quotient_rel_abs) kuncar@47937: then show ?thesis using assms(1) by (simp add: Quotient_abs_rep) kuncar@47937: qed kuncar@47937: huffman@47536: lemma Quotient_symp: "symp R" kuncar@47308: using a unfolding Quotient_def using sympI by (metis (full_types)) kuncar@47308: huffman@47536: lemma Quotient_transp: "transp R" kuncar@47308: using a unfolding Quotient_def using transpI by (metis (full_types)) kuncar@47308: huffman@47536: lemma Quotient_part_equivp: "part_equivp R" huffman@47536: by (metis Quotient_rep_reflp Quotient_symp Quotient_transp part_equivpI) huffman@47536: huffman@47536: end kuncar@47308: kuncar@47308: lemma identity_quotient: "Quotient (op =) id id (op =)" kuncar@47308: unfolding Quotient_def by simp kuncar@47308: huffman@47652: text {* TODO: Use one of these alternatives as the real definition. *} huffman@47652: kuncar@47308: lemma Quotient_alt_def: kuncar@47308: "Quotient R Abs Rep T \ kuncar@47308: (\a b. T a b \ Abs a = b) \ kuncar@47308: (\b. T (Rep b) b) \ kuncar@47308: (\x y. R x y \ T x (Abs x) \ T y (Abs y) \ Abs x = Abs y)" kuncar@47308: apply safe kuncar@47308: apply (simp (no_asm_use) only: Quotient_def, fast) kuncar@47308: apply (simp (no_asm_use) only: Quotient_def, fast) kuncar@47308: apply (simp (no_asm_use) only: Quotient_def, fast) kuncar@47308: apply (simp (no_asm_use) only: Quotient_def, fast) kuncar@47308: apply (simp (no_asm_use) only: Quotient_def, fast) kuncar@47308: apply (simp (no_asm_use) only: Quotient_def, fast) kuncar@47308: apply (rule QuotientI) kuncar@47308: apply simp kuncar@47308: apply metis kuncar@47308: apply simp kuncar@47308: apply (rule ext, rule ext, metis) kuncar@47308: done kuncar@47308: kuncar@47308: lemma Quotient_alt_def2: kuncar@47308: "Quotient R Abs Rep T \ kuncar@47308: (\a b. T a b \ Abs a = b) \ kuncar@47308: (\b. T (Rep b) b) \ kuncar@47308: (\x y. R x y \ T x (Abs y) \ T y (Abs x))" kuncar@47308: unfolding Quotient_alt_def by (safe, metis+) kuncar@47308: huffman@47652: lemma Quotient_alt_def3: huffman@47652: "Quotient R Abs Rep T \ huffman@47652: (\a b. T a b \ Abs a = b) \ (\b. T (Rep b) b) \ huffman@47652: (\x y. R x y \ (\z. T x z \ T y z))" huffman@47652: unfolding Quotient_alt_def2 by (safe, metis+) huffman@47652: huffman@47652: lemma Quotient_alt_def4: huffman@47652: "Quotient R Abs Rep T \ huffman@47652: (\a b. T a b \ Abs a = b) \ (\b. T (Rep b) b) \ R = T OO conversep T" huffman@47652: unfolding Quotient_alt_def3 fun_eq_iff by auto huffman@47652: kuncar@47308: lemma fun_quotient: kuncar@47308: assumes 1: "Quotient R1 abs1 rep1 T1" kuncar@47308: assumes 2: "Quotient R2 abs2 rep2 T2" kuncar@47308: shows "Quotient (R1 ===> R2) (rep1 ---> abs2) (abs1 ---> rep2) (T1 ===> T2)" kuncar@47308: using assms unfolding Quotient_alt_def2 kuncar@47308: unfolding fun_rel_def fun_eq_iff map_fun_apply kuncar@47308: by (safe, metis+) kuncar@47308: kuncar@47308: lemma apply_rsp: kuncar@47308: fixes f g::"'a \ 'c" kuncar@47308: assumes q: "Quotient R1 Abs1 Rep1 T1" kuncar@47308: and a: "(R1 ===> R2) f g" "R1 x y" kuncar@47308: shows "R2 (f x) (g y)" kuncar@47308: using a by (auto elim: fun_relE) kuncar@47308: kuncar@47308: lemma apply_rsp': kuncar@47308: assumes a: "(R1 ===> R2) f g" "R1 x y" kuncar@47308: shows "R2 (f x) (g y)" kuncar@47308: using a by (auto elim: fun_relE) kuncar@47308: kuncar@47308: lemma apply_rsp'': kuncar@47308: assumes "Quotient R Abs Rep T" kuncar@47308: and "(R ===> S) f f" kuncar@47308: shows "S (f (Rep x)) (f (Rep x))" kuncar@47308: proof - kuncar@47308: from assms(1) have "R (Rep x) (Rep x)" by (rule Quotient_rep_reflp) kuncar@47308: then show ?thesis using assms(2) by (auto intro: apply_rsp') kuncar@47308: qed kuncar@47308: kuncar@47308: subsection {* Quotient composition *} kuncar@47308: kuncar@47308: lemma Quotient_compose: kuncar@47308: assumes 1: "Quotient R1 Abs1 Rep1 T1" kuncar@47308: assumes 2: "Quotient R2 Abs2 Rep2 T2" kuncar@47308: shows "Quotient (T1 OO R2 OO conversep T1) (Abs2 \ Abs1) (Rep1 \ Rep2) (T1 OO T2)" kuncar@51994: using assms unfolding Quotient_alt_def4 by fastforce kuncar@47308: kuncar@47521: lemma equivp_reflp2: kuncar@47521: "equivp R \ reflp R" kuncar@47521: by (erule equivpE) kuncar@47521: huffman@47544: subsection {* Respects predicate *} huffman@47544: huffman@47544: definition Respects :: "('a \ 'a \ bool) \ 'a set" huffman@47544: where "Respects R = {x. R x x}" huffman@47544: huffman@47544: lemma in_respects: "x \ Respects R \ R x x" huffman@47544: unfolding Respects_def by simp huffman@47544: kuncar@47308: subsection {* Invariant *} kuncar@47308: kuncar@47308: definition invariant :: "('a \ bool) \ 'a \ 'a \ bool" kuncar@47308: where "invariant R = (\x y. R x \ x = y)" kuncar@47308: kuncar@47308: lemma invariant_to_eq: kuncar@47308: assumes "invariant P x y" kuncar@47308: shows "x = y" kuncar@47308: using assms by (simp add: invariant_def) kuncar@47308: kuncar@47308: lemma fun_rel_eq_invariant: kuncar@47308: shows "((invariant R) ===> S) = (\f g. \x. R x \ S (f x) (g x))" kuncar@47308: by (auto simp add: invariant_def fun_rel_def) kuncar@47308: kuncar@47308: lemma invariant_same_args: kuncar@47308: shows "invariant P x x \ P x" kuncar@47308: using assms by (auto simp add: invariant_def) kuncar@47308: kuncar@53952: lemma invariant_transfer [transfer_rule]: kuncar@53952: assumes [transfer_rule]: "bi_unique A" kuncar@53952: shows "((A ===> op=) ===> A ===> A ===> op=) Lifting.invariant Lifting.invariant" kuncar@53952: unfolding invariant_def[abs_def] by transfer_prover kuncar@53952: kuncar@47361: lemma UNIV_typedef_to_Quotient: kuncar@47308: assumes "type_definition Rep Abs UNIV" kuncar@47361: and T_def: "T \ (\x y. x = Rep y)" kuncar@47308: shows "Quotient (op =) Abs Rep T" kuncar@47308: proof - kuncar@47308: interpret type_definition Rep Abs UNIV by fact kuncar@47361: from Abs_inject Rep_inverse Abs_inverse T_def show ?thesis kuncar@47361: by (fastforce intro!: QuotientI fun_eq_iff) kuncar@47308: qed kuncar@47308: kuncar@47361: lemma UNIV_typedef_to_equivp: kuncar@47308: fixes Abs :: "'a \ 'b" kuncar@47308: and Rep :: "'b \ 'a" kuncar@47308: assumes "type_definition Rep Abs (UNIV::'a set)" kuncar@47308: shows "equivp (op=::'a\'a\bool)" kuncar@47308: by (rule identity_equivp) kuncar@47308: huffman@47354: lemma typedef_to_Quotient: kuncar@47361: assumes "type_definition Rep Abs S" kuncar@47361: and T_def: "T \ (\x y. x = Rep y)" kuncar@47501: shows "Quotient (invariant (\x. x \ S)) Abs Rep T" kuncar@47361: proof - kuncar@47361: interpret type_definition Rep Abs S by fact kuncar@47361: from Rep Abs_inject Rep_inverse Abs_inverse T_def show ?thesis kuncar@47361: by (auto intro!: QuotientI simp: invariant_def fun_eq_iff) kuncar@47361: qed kuncar@47361: kuncar@47361: lemma typedef_to_part_equivp: kuncar@47361: assumes "type_definition Rep Abs S" kuncar@47501: shows "part_equivp (invariant (\x. x \ S))" kuncar@47361: proof (intro part_equivpI) kuncar@47361: interpret type_definition Rep Abs S by fact kuncar@47501: show "\x. invariant (\x. x \ S) x x" using Rep by (auto simp: invariant_def) kuncar@47361: next kuncar@47501: show "symp (invariant (\x. x \ S))" by (auto intro: sympI simp: invariant_def) kuncar@47361: next kuncar@47501: show "transp (invariant (\x. x \ S))" by (auto intro: transpI simp: invariant_def) kuncar@47361: qed kuncar@47361: kuncar@47361: lemma open_typedef_to_Quotient: kuncar@47308: assumes "type_definition Rep Abs {x. P x}" huffman@47354: and T_def: "T \ (\x y. x = Rep y)" kuncar@47308: shows "Quotient (invariant P) Abs Rep T" huffman@47651: using typedef_to_Quotient [OF assms] by simp kuncar@47308: kuncar@47361: lemma open_typedef_to_part_equivp: kuncar@47308: assumes "type_definition Rep Abs {x. P x}" kuncar@47308: shows "part_equivp (invariant P)" huffman@47651: using typedef_to_part_equivp [OF assms] by simp kuncar@47308: huffman@47376: text {* Generating transfer rules for quotients. *} huffman@47376: huffman@47537: context huffman@47537: fixes R Abs Rep T huffman@47537: assumes 1: "Quotient R Abs Rep T" huffman@47537: begin huffman@47376: huffman@47537: lemma Quotient_right_unique: "right_unique T" huffman@47537: using 1 unfolding Quotient_alt_def right_unique_def by metis huffman@47537: huffman@47537: lemma Quotient_right_total: "right_total T" huffman@47537: using 1 unfolding Quotient_alt_def right_total_def by metis huffman@47537: huffman@47537: lemma Quotient_rel_eq_transfer: "(T ===> T ===> op =) R (op =)" huffman@47537: using 1 unfolding Quotient_alt_def fun_rel_def by simp huffman@47376: huffman@47538: lemma Quotient_abs_induct: huffman@47538: assumes "\y. R y y \ P (Abs y)" shows "P x" huffman@47538: using 1 assms unfolding Quotient_def by metis huffman@47538: huffman@47537: end huffman@47537: huffman@47537: text {* Generating transfer rules for total quotients. *} huffman@47376: huffman@47537: context huffman@47537: fixes R Abs Rep T huffman@47537: assumes 1: "Quotient R Abs Rep T" and 2: "reflp R" huffman@47537: begin huffman@47376: huffman@47537: lemma Quotient_bi_total: "bi_total T" huffman@47537: using 1 2 unfolding Quotient_alt_def bi_total_def reflp_def by auto huffman@47537: huffman@47537: lemma Quotient_id_abs_transfer: "(op = ===> T) (\x. x) Abs" huffman@47537: using 1 2 unfolding Quotient_alt_def reflp_def fun_rel_def by simp huffman@47537: huffman@47575: lemma Quotient_total_abs_induct: "(\y. P (Abs y)) \ P x" huffman@47575: using 1 2 assms unfolding Quotient_alt_def reflp_def by metis huffman@47575: huffman@47889: lemma Quotient_total_abs_eq_iff: "Abs x = Abs y \ R x y" huffman@47889: using Quotient_rel [OF 1] 2 unfolding reflp_def by simp huffman@47889: huffman@47537: end huffman@47376: huffman@47368: text {* Generating transfer rules for a type defined with @{text "typedef"}. *} huffman@47368: huffman@47534: context huffman@47534: fixes Rep Abs A T huffman@47368: assumes type: "type_definition Rep Abs A" huffman@47534: assumes T_def: "T \ (\(x::'a) (y::'b). x = Rep y)" huffman@47534: begin huffman@47534: kuncar@51994: lemma typedef_left_unique: "left_unique T" kuncar@51994: unfolding left_unique_def T_def kuncar@51994: by (simp add: type_definition.Rep_inject [OF type]) kuncar@51994: huffman@47534: lemma typedef_bi_unique: "bi_unique T" huffman@47368: unfolding bi_unique_def T_def huffman@47368: by (simp add: type_definition.Rep_inject [OF type]) huffman@47368: kuncar@51374: (* the following two theorems are here only for convinience *) kuncar@51374: kuncar@51374: lemma typedef_right_unique: "right_unique T" kuncar@51374: using T_def type Quotient_right_unique typedef_to_Quotient kuncar@51374: by blast kuncar@51374: kuncar@51374: lemma typedef_right_total: "right_total T" kuncar@51374: using T_def type Quotient_right_total typedef_to_Quotient kuncar@51374: by blast kuncar@51374: huffman@47535: lemma typedef_rep_transfer: "(T ===> op =) (\x. x) Rep" huffman@47535: unfolding fun_rel_def T_def by simp huffman@47535: huffman@47534: end huffman@47534: huffman@47368: text {* Generating the correspondence rule for a constant defined with huffman@47368: @{text "lift_definition"}. *} huffman@47368: huffman@47351: lemma Quotient_to_transfer: huffman@47351: assumes "Quotient R Abs Rep T" and "R c c" and "c' \ Abs c" huffman@47351: shows "T c c'" huffman@47351: using assms by (auto dest: Quotient_cr_rel) huffman@47351: kuncar@47982: text {* Proving reflexivity *} kuncar@47982: kuncar@51994: definition reflp' :: "('a \ 'a \ bool) \ bool" where "reflp' R \ reflp R" kuncar@47982: kuncar@47982: lemma Quotient_to_left_total: kuncar@47982: assumes q: "Quotient R Abs Rep T" kuncar@47982: and r_R: "reflp R" kuncar@47982: shows "left_total T" kuncar@47982: using r_R Quotient_cr_rel[OF q] unfolding left_total_def by (auto elim: reflpE) kuncar@47982: kuncar@47982: lemma reflp_Quotient_composition: kuncar@51994: assumes "left_total R" kuncar@51994: assumes "reflp T" kuncar@51994: shows "reflp (R OO T OO R\\)" kuncar@51994: using assms unfolding reflp_def left_total_def by fast kuncar@51994: kuncar@51994: lemma reflp_fun1: kuncar@51994: assumes "is_equality R" kuncar@51994: assumes "reflp' S" kuncar@51994: shows "reflp (R ===> S)" kuncar@51994: using assms unfolding is_equality_def reflp'_def reflp_def fun_rel_def by blast kuncar@51994: kuncar@51994: lemma reflp_fun2: kuncar@51994: assumes "is_equality R" kuncar@51994: assumes "is_equality S" kuncar@51994: shows "reflp (R ===> S)" kuncar@51994: using assms unfolding is_equality_def reflp_def fun_rel_def by blast kuncar@51994: kuncar@51994: lemma is_equality_Quotient_composition: kuncar@51994: assumes "is_equality T" kuncar@51994: assumes "left_total R" kuncar@51994: assumes "left_unique R" kuncar@51994: shows "is_equality (R OO T OO R\\)" kuncar@51994: using assms unfolding is_equality_def left_total_def left_unique_def OO_def conversep_iff kuncar@51994: by fastforce kuncar@47982: kuncar@52307: lemma left_total_composition: "left_total R \ left_total S \ left_total (R OO S)" kuncar@52307: unfolding left_total_def OO_def by fast kuncar@52307: kuncar@52307: lemma left_unique_composition: "left_unique R \ left_unique S \ left_unique (R OO S)" kuncar@52307: unfolding left_unique_def OO_def by fast kuncar@52307: kuncar@47982: lemma reflp_equality: "reflp (op =)" kuncar@47982: by (auto intro: reflpI) kuncar@47982: kuncar@51374: text {* Proving a parametrized correspondence relation *} kuncar@51374: kuncar@51374: lemma eq_OO: "op= OO R = R" kuncar@51374: unfolding OO_def by metis kuncar@51374: kuncar@51374: definition POS :: "('a \ 'b \ bool) \ ('a \ 'b \ bool) \ bool" where kuncar@51374: "POS A B \ A \ B" kuncar@51374: kuncar@51374: definition NEG :: "('a \ 'b \ bool) \ ('a \ 'b \ bool) \ bool" where kuncar@51374: "NEG A B \ B \ A" kuncar@51374: kuncar@51374: (* kuncar@51374: The following two rules are here because we don't have any proper kuncar@51374: left-unique ant left-total relations. Left-unique and left-total kuncar@51374: assumptions show up in distributivity rules for the function type. kuncar@51374: *) kuncar@51374: kuncar@51374: lemma bi_unique_left_unique[transfer_rule]: "bi_unique R \ left_unique R" kuncar@51374: unfolding bi_unique_def left_unique_def by blast kuncar@51374: kuncar@51374: lemma bi_total_left_total[transfer_rule]: "bi_total R \ left_total R" kuncar@51374: unfolding bi_total_def left_total_def by blast kuncar@51374: kuncar@51374: lemma pos_OO_eq: kuncar@51374: shows "POS (A OO op=) A" kuncar@51374: unfolding POS_def OO_def by blast kuncar@51374: kuncar@51374: lemma pos_eq_OO: kuncar@51374: shows "POS (op= OO A) A" kuncar@51374: unfolding POS_def OO_def by blast kuncar@51374: kuncar@51374: lemma neg_OO_eq: kuncar@51374: shows "NEG (A OO op=) A" kuncar@51374: unfolding NEG_def OO_def by auto kuncar@51374: kuncar@51374: lemma neg_eq_OO: kuncar@51374: shows "NEG (op= OO A) A" kuncar@51374: unfolding NEG_def OO_def by blast kuncar@51374: kuncar@51374: lemma POS_trans: kuncar@51374: assumes "POS A B" kuncar@51374: assumes "POS B C" kuncar@51374: shows "POS A C" kuncar@51374: using assms unfolding POS_def by auto kuncar@51374: kuncar@51374: lemma NEG_trans: kuncar@51374: assumes "NEG A B" kuncar@51374: assumes "NEG B C" kuncar@51374: shows "NEG A C" kuncar@51374: using assms unfolding NEG_def by auto kuncar@51374: kuncar@51374: lemma POS_NEG: kuncar@51374: "POS A B \ NEG B A" kuncar@51374: unfolding POS_def NEG_def by auto kuncar@51374: kuncar@51374: lemma NEG_POS: kuncar@51374: "NEG A B \ POS B A" kuncar@51374: unfolding POS_def NEG_def by auto kuncar@51374: kuncar@51374: lemma POS_pcr_rule: kuncar@51374: assumes "POS (A OO B) C" kuncar@51374: shows "POS (A OO B OO X) (C OO X)" kuncar@51374: using assms unfolding POS_def OO_def by blast kuncar@51374: kuncar@51374: lemma NEG_pcr_rule: kuncar@51374: assumes "NEG (A OO B) C" kuncar@51374: shows "NEG (A OO B OO X) (C OO X)" kuncar@51374: using assms unfolding NEG_def OO_def by blast kuncar@51374: kuncar@51374: lemma POS_apply: kuncar@51374: assumes "POS R R'" kuncar@51374: assumes "R f g" kuncar@51374: shows "R' f g" kuncar@51374: using assms unfolding POS_def by auto kuncar@51374: kuncar@51374: text {* Proving a parametrized correspondence relation *} kuncar@51374: kuncar@51374: lemma fun_mono: kuncar@51374: assumes "A \ C" kuncar@51374: assumes "B \ D" kuncar@51374: shows "(A ===> B) \ (C ===> D)" kuncar@51374: using assms unfolding fun_rel_def by blast kuncar@51374: kuncar@51374: lemma pos_fun_distr: "((R ===> S) OO (R' ===> S')) \ ((R OO R') ===> (S OO S'))" kuncar@51374: unfolding OO_def fun_rel_def by blast kuncar@51374: kuncar@51374: lemma functional_relation: "right_unique R \ left_total R \ \x. \!y. R x y" kuncar@51374: unfolding right_unique_def left_total_def by blast kuncar@51374: kuncar@51374: lemma functional_converse_relation: "left_unique R \ right_total R \ \y. \!x. R x y" kuncar@51374: unfolding left_unique_def right_total_def by blast kuncar@51374: kuncar@51374: lemma neg_fun_distr1: kuncar@51374: assumes 1: "left_unique R" "right_total R" kuncar@51374: assumes 2: "right_unique R'" "left_total R'" kuncar@51374: shows "(R OO R' ===> S OO S') \ ((R ===> S) OO (R' ===> S')) " kuncar@51374: using functional_relation[OF 2] functional_converse_relation[OF 1] kuncar@51374: unfolding fun_rel_def OO_def kuncar@51374: apply clarify kuncar@51374: apply (subst all_comm) kuncar@51374: apply (subst all_conj_distrib[symmetric]) kuncar@51374: apply (intro choice) kuncar@51374: by metis kuncar@51374: kuncar@51374: lemma neg_fun_distr2: kuncar@51374: assumes 1: "right_unique R'" "left_total R'" kuncar@51374: assumes 2: "left_unique S'" "right_total S'" kuncar@51374: shows "(R OO R' ===> S OO S') \ ((R ===> S) OO (R' ===> S'))" kuncar@51374: using functional_converse_relation[OF 2] functional_relation[OF 1] kuncar@51374: unfolding fun_rel_def OO_def kuncar@51374: apply clarify kuncar@51374: apply (subst all_comm) kuncar@51374: apply (subst all_conj_distrib[symmetric]) kuncar@51374: apply (intro choice) kuncar@51374: by metis kuncar@51374: kuncar@51956: subsection {* Domains *} kuncar@51956: kuncar@51956: lemma pcr_Domainp_par_left_total: kuncar@51956: assumes "Domainp B = P" kuncar@51956: assumes "left_total A" kuncar@51956: assumes "(A ===> op=) P' P" kuncar@51956: shows "Domainp (A OO B) = P'" kuncar@51956: using assms kuncar@51956: unfolding Domainp_iff[abs_def] OO_def bi_unique_def left_total_def fun_rel_def kuncar@51956: by (fast intro: fun_eq_iff) kuncar@51956: kuncar@51956: lemma pcr_Domainp_par: kuncar@51956: assumes "Domainp B = P2" kuncar@51956: assumes "Domainp A = P1" kuncar@51956: assumes "(A ===> op=) P2' P2" kuncar@51956: shows "Domainp (A OO B) = (inf P1 P2')" kuncar@51956: using assms unfolding fun_rel_def Domainp_iff[abs_def] OO_def kuncar@51956: by (fast intro: fun_eq_iff) kuncar@51956: kuncar@53151: definition rel_pred_comp :: "('a => 'b => bool) => ('b => bool) => 'a => bool" kuncar@51956: where "rel_pred_comp R P \ \x. \y. R x y \ P y" kuncar@51956: kuncar@51956: lemma pcr_Domainp: kuncar@51956: assumes "Domainp B = P" kuncar@53151: shows "Domainp (A OO B) = (\x. \y. A x y \ P y)" kuncar@53151: using assms by blast kuncar@51956: kuncar@51956: lemma pcr_Domainp_total: kuncar@51956: assumes "bi_total B" kuncar@51956: assumes "Domainp A = P" kuncar@51956: shows "Domainp (A OO B) = P" kuncar@51956: using assms unfolding bi_total_def kuncar@51956: by fast kuncar@51956: kuncar@51956: lemma Quotient_to_Domainp: kuncar@51956: assumes "Quotient R Abs Rep T" kuncar@51956: shows "Domainp T = (\x. R x x)" kuncar@51956: by (simp add: Domainp_iff[abs_def] Quotient_cr_rel[OF assms]) kuncar@51956: kuncar@51956: lemma invariant_to_Domainp: kuncar@51956: assumes "Quotient (Lifting.invariant P) Abs Rep T" kuncar@51956: shows "Domainp T = P" kuncar@51956: by (simp add: invariant_def Domainp_iff[abs_def] Quotient_cr_rel[OF assms]) kuncar@51956: kuncar@53011: end kuncar@53011: kuncar@47308: subsection {* ML setup *} kuncar@47308: wenzelm@48891: ML_file "Tools/Lifting/lifting_util.ML" kuncar@47308: wenzelm@48891: ML_file "Tools/Lifting/lifting_info.ML" kuncar@47308: setup Lifting_Info.setup kuncar@47308: kuncar@51994: lemmas [reflexivity_rule] = kuncar@52036: reflp_equality reflp_Quotient_composition is_equality_Quotient_composition kuncar@52307: left_total_fun left_unique_fun left_total_eq left_unique_eq left_total_composition kuncar@52307: left_unique_composition kuncar@51994: kuncar@51994: text {* add @{thm reflp_fun1} and @{thm reflp_fun2} manually through ML kuncar@51994: because we don't want to get reflp' variant of these theorems *} kuncar@51994: kuncar@51994: setup{* kuncar@51994: Context.theory_map kuncar@51994: (fold kuncar@51994: (snd oo (Thm.apply_attribute Lifting_Info.add_reflexivity_rule_raw_attribute)) kuncar@51994: [@{thm reflp_fun1}, @{thm reflp_fun2}]) kuncar@51994: *} kuncar@51374: kuncar@51374: (* setup for the function type *) kuncar@47777: declare fun_quotient[quot_map] kuncar@51374: declare fun_mono[relator_mono] kuncar@51374: lemmas [relator_distr] = pos_fun_distr neg_fun_distr1 neg_fun_distr2 kuncar@47308: wenzelm@48891: ML_file "Tools/Lifting/lifting_term.ML" kuncar@47308: wenzelm@48891: ML_file "Tools/Lifting/lifting_def.ML" kuncar@47308: wenzelm@48891: ML_file "Tools/Lifting/lifting_setup.ML" kuncar@47308: kuncar@51994: hide_const (open) invariant POS NEG reflp' kuncar@47308: kuncar@47308: end