kaliszyk@35222: (* Title: Quotient.thy kaliszyk@35222: Author: Cezary Kaliszyk and Christian Urban kaliszyk@35222: *) kaliszyk@35222: huffman@35294: header {* Definition of Quotient Types *} huffman@35294: kaliszyk@35222: theory Quotient blanchet@35827: imports Plain Sledgehammer kaliszyk@35222: uses kaliszyk@35222: ("~~/src/HOL/Tools/Quotient/quotient_info.ML") kaliszyk@35222: ("~~/src/HOL/Tools/Quotient/quotient_typ.ML") kaliszyk@35222: ("~~/src/HOL/Tools/Quotient/quotient_def.ML") kaliszyk@35222: ("~~/src/HOL/Tools/Quotient/quotient_term.ML") kaliszyk@35222: ("~~/src/HOL/Tools/Quotient/quotient_tacs.ML") kaliszyk@35222: begin kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: text {* kaliszyk@35222: Basic definition for equivalence relations kaliszyk@35222: that are represented by predicates. kaliszyk@35222: *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: "equivp E \ \x y. E x y = (E x = E y)" kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: "reflp E \ \x. E x x" kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: "symp E \ \x y. E x y \ E y x" kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: "transp E \ \x y z. E x y \ E y z \ E x z" kaliszyk@35222: kaliszyk@35222: lemma equivp_reflp_symp_transp: kaliszyk@35222: shows "equivp E = (reflp E \ symp E \ transp E)" kaliszyk@35222: unfolding equivp_def reflp_def symp_def transp_def expand_fun_eq kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma equivp_reflp: kaliszyk@35222: shows "equivp E \ E x x" kaliszyk@35222: by (simp only: equivp_reflp_symp_transp reflp_def) kaliszyk@35222: kaliszyk@35222: lemma equivp_symp: kaliszyk@35222: shows "equivp E \ E x y \ E y x" kaliszyk@35222: by (metis equivp_reflp_symp_transp symp_def) kaliszyk@35222: kaliszyk@35222: lemma equivp_transp: kaliszyk@35222: shows "equivp E \ E x y \ E y z \ E x z" kaliszyk@35222: by (metis equivp_reflp_symp_transp transp_def) kaliszyk@35222: kaliszyk@35222: lemma equivpI: kaliszyk@35222: assumes "reflp R" "symp R" "transp R" kaliszyk@35222: shows "equivp R" kaliszyk@35222: using assms by (simp add: equivp_reflp_symp_transp) kaliszyk@35222: kaliszyk@35222: lemma identity_equivp: kaliszyk@35222: shows "equivp (op =)" kaliszyk@35222: unfolding equivp_def kaliszyk@35222: by auto kaliszyk@35222: kaliszyk@35222: text {* Partial equivalences: not yet used anywhere *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: "part_equivp E \ (\x. E x x) \ (\x y. E x y = (E x x \ E y y \ (E x = E y)))" kaliszyk@35222: kaliszyk@35222: lemma equivp_implies_part_equivp: kaliszyk@35222: assumes a: "equivp E" kaliszyk@35222: shows "part_equivp E" kaliszyk@35222: using a kaliszyk@35222: unfolding equivp_def part_equivp_def kaliszyk@35222: by auto kaliszyk@35222: kaliszyk@35222: text {* Composition of Relations *} kaliszyk@35222: kaliszyk@35222: abbreviation kaliszyk@35222: rel_conj (infixr "OOO" 75) kaliszyk@35222: where kaliszyk@35222: "r1 OOO r2 \ r1 OO r2 OO r1" kaliszyk@35222: kaliszyk@35222: lemma eq_comp_r: kaliszyk@35222: shows "((op =) OOO R) = R" kaliszyk@35222: by (auto simp add: expand_fun_eq) kaliszyk@35222: huffman@35294: subsection {* Respects predicate *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: Respects kaliszyk@35222: where kaliszyk@35222: "Respects R x \ R x x" kaliszyk@35222: kaliszyk@35222: lemma in_respects: kaliszyk@35222: shows "(x \ Respects R) = R x x" kaliszyk@35222: unfolding mem_def Respects_def kaliszyk@35222: by simp kaliszyk@35222: huffman@35294: subsection {* Function map and function relation *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: fun_map (infixr "--->" 55) kaliszyk@35222: where kaliszyk@35222: [simp]: "fun_map f g h x = g (h (f x))" kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: fun_rel (infixr "===>" 55) kaliszyk@35222: where kaliszyk@35222: [simp]: "fun_rel E1 E2 f g = (\x y. E1 x y \ E2 (f x) (g y))" kaliszyk@35222: kaliszyk@36276: lemma fun_relI [intro]: kaliszyk@36276: assumes "\a b. P a b \ Q (x a) (y b)" kaliszyk@36276: shows "(P ===> Q) x y" kaliszyk@36276: using assms by (simp add: fun_rel_def) kaliszyk@35222: kaliszyk@35222: lemma fun_map_id: kaliszyk@35222: shows "(id ---> id) = id" kaliszyk@35222: by (simp add: expand_fun_eq id_def) kaliszyk@35222: kaliszyk@35222: lemma fun_rel_eq: kaliszyk@35222: shows "((op =) ===> (op =)) = (op =)" kaliszyk@35222: by (simp add: expand_fun_eq) kaliszyk@35222: kaliszyk@35222: lemma fun_rel_id: kaliszyk@35222: assumes a: "\x y. R1 x y \ R2 (f x) (g y)" kaliszyk@35222: shows "(R1 ===> R2) f g" kaliszyk@35222: using a by simp kaliszyk@35222: kaliszyk@35222: lemma fun_rel_id_asm: kaliszyk@35222: assumes a: "\x y. R1 x y \ (A \ R2 (f x) (g y))" kaliszyk@35222: shows "A \ (R1 ===> R2) f g" kaliszyk@35222: using a by auto kaliszyk@35222: kaliszyk@35222: huffman@35294: subsection {* Quotient Predicate *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: "Quotient E Abs Rep \ kaliszyk@35222: (\a. Abs (Rep a) = a) \ (\a. E (Rep a) (Rep a)) \ kaliszyk@35222: (\r s. E r s = (E r r \ E s s \ (Abs r = Abs s)))" kaliszyk@35222: kaliszyk@35222: lemma Quotient_abs_rep: kaliszyk@35222: assumes a: "Quotient E Abs Rep" kaliszyk@35222: shows "Abs (Rep a) = a" kaliszyk@35222: using a kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: by simp kaliszyk@35222: kaliszyk@35222: lemma Quotient_rep_reflp: kaliszyk@35222: assumes a: "Quotient E Abs Rep" kaliszyk@35222: shows "E (Rep a) (Rep a)" kaliszyk@35222: using a kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma Quotient_rel: kaliszyk@35222: assumes a: "Quotient E Abs Rep" kaliszyk@35222: shows " E r s = (E r r \ E s s \ (Abs r = Abs s))" kaliszyk@35222: using a kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma Quotient_rel_rep: kaliszyk@35222: assumes a: "Quotient R Abs Rep" kaliszyk@35222: shows "R (Rep a) (Rep b) = (a = b)" kaliszyk@35222: using a kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: lemma Quotient_rep_abs: kaliszyk@35222: assumes a: "Quotient R Abs Rep" kaliszyk@35222: shows "R r r \ R (Rep (Abs r)) r" kaliszyk@35222: using a unfolding Quotient_def kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma Quotient_rel_abs: kaliszyk@35222: assumes a: "Quotient E Abs Rep" kaliszyk@35222: shows "E r s \ Abs r = Abs s" kaliszyk@35222: using a unfolding Quotient_def kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma Quotient_symp: kaliszyk@35222: assumes a: "Quotient E Abs Rep" kaliszyk@35222: shows "symp E" kaliszyk@35222: using a unfolding Quotient_def symp_def kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: lemma Quotient_transp: kaliszyk@35222: assumes a: "Quotient E Abs Rep" kaliszyk@35222: shows "transp E" kaliszyk@35222: using a unfolding Quotient_def transp_def kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: lemma identity_quotient: kaliszyk@35222: shows "Quotient (op =) id id" kaliszyk@35222: unfolding Quotient_def id_def kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma fun_quotient: kaliszyk@35222: assumes q1: "Quotient R1 abs1 rep1" kaliszyk@35222: and q2: "Quotient R2 abs2 rep2" kaliszyk@35222: shows "Quotient (R1 ===> R2) (rep1 ---> abs2) (abs1 ---> rep2)" kaliszyk@35222: proof - kaliszyk@35222: have "\a. (rep1 ---> abs2) ((abs1 ---> rep2) a) = a" kaliszyk@35222: using q1 q2 kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: unfolding expand_fun_eq kaliszyk@35222: by simp kaliszyk@35222: moreover kaliszyk@35222: have "\a. (R1 ===> R2) ((abs1 ---> rep2) a) ((abs1 ---> rep2) a)" kaliszyk@35222: using q1 q2 kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: by (simp (no_asm)) (metis) kaliszyk@35222: moreover kaliszyk@35222: have "\r s. (R1 ===> R2) r s = ((R1 ===> R2) r r \ (R1 ===> R2) s s \ kaliszyk@35222: (rep1 ---> abs2) r = (rep1 ---> abs2) s)" kaliszyk@35222: unfolding expand_fun_eq kaliszyk@35222: apply(auto) kaliszyk@35222: using q1 q2 unfolding Quotient_def kaliszyk@35222: apply(metis) kaliszyk@35222: using q1 q2 unfolding Quotient_def kaliszyk@35222: apply(metis) kaliszyk@35222: using q1 q2 unfolding Quotient_def kaliszyk@35222: apply(metis) kaliszyk@35222: using q1 q2 unfolding Quotient_def kaliszyk@35222: apply(metis) kaliszyk@35222: done kaliszyk@35222: ultimately kaliszyk@35222: show "Quotient (R1 ===> R2) (rep1 ---> abs2) (abs1 ---> rep2)" kaliszyk@35222: unfolding Quotient_def by blast kaliszyk@35222: qed kaliszyk@35222: kaliszyk@35222: lemma abs_o_rep: kaliszyk@35222: assumes a: "Quotient R Abs Rep" kaliszyk@35222: shows "Abs o Rep = id" kaliszyk@35222: unfolding expand_fun_eq kaliszyk@35222: by (simp add: Quotient_abs_rep[OF a]) kaliszyk@35222: kaliszyk@35222: lemma equals_rsp: kaliszyk@35222: assumes q: "Quotient R Abs Rep" kaliszyk@35222: and a: "R xa xb" "R ya yb" kaliszyk@35222: shows "R xa ya = R xb yb" kaliszyk@35222: using a Quotient_symp[OF q] Quotient_transp[OF q] kaliszyk@35222: unfolding symp_def transp_def kaliszyk@35222: by blast kaliszyk@35222: kaliszyk@35222: lemma lambda_prs: kaliszyk@35222: assumes q1: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and q2: "Quotient R2 Abs2 Rep2" kaliszyk@35222: shows "(Rep1 ---> Abs2) (\x. Rep2 (f (Abs1 x))) = (\x. f x)" kaliszyk@35222: unfolding expand_fun_eq kaliszyk@35222: using Quotient_abs_rep[OF q1] Quotient_abs_rep[OF q2] kaliszyk@35222: by simp kaliszyk@35222: kaliszyk@35222: lemma lambda_prs1: kaliszyk@35222: assumes q1: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and q2: "Quotient R2 Abs2 Rep2" kaliszyk@35222: shows "(Rep1 ---> Abs2) (\x. (Abs1 ---> Rep2) f x) = (\x. f x)" kaliszyk@35222: unfolding expand_fun_eq kaliszyk@35222: using Quotient_abs_rep[OF q1] Quotient_abs_rep[OF q2] kaliszyk@35222: by simp kaliszyk@35222: kaliszyk@35222: lemma rep_abs_rsp: kaliszyk@35222: assumes q: "Quotient R Abs Rep" kaliszyk@35222: and a: "R x1 x2" kaliszyk@35222: shows "R x1 (Rep (Abs x2))" kaliszyk@35222: using a Quotient_rel[OF q] Quotient_abs_rep[OF q] Quotient_rep_reflp[OF q] kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: lemma rep_abs_rsp_left: kaliszyk@35222: assumes q: "Quotient R Abs Rep" kaliszyk@35222: and a: "R x1 x2" kaliszyk@35222: shows "R (Rep (Abs x1)) x2" kaliszyk@35222: using a Quotient_rel[OF q] Quotient_abs_rep[OF q] Quotient_rep_reflp[OF q] kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: text{* kaliszyk@35222: In the following theorem R1 can be instantiated with anything, kaliszyk@35222: but we know some of the types of the Rep and Abs functions; kaliszyk@35222: so by solving Quotient assumptions we can get a unique R1 that kaliszyk@35236: will be provable; which is why we need to use @{text apply_rsp} and kaliszyk@35222: not the primed version *} kaliszyk@35222: kaliszyk@35222: lemma apply_rsp: kaliszyk@35222: fixes f g::"'a \ 'c" kaliszyk@35222: assumes q: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and a: "(R1 ===> R2) f g" "R1 x y" kaliszyk@35222: shows "R2 (f x) (g y)" kaliszyk@35222: using a by simp kaliszyk@35222: kaliszyk@35222: lemma apply_rsp': kaliszyk@35222: assumes a: "(R1 ===> R2) f g" "R1 x y" kaliszyk@35222: shows "R2 (f x) (g y)" kaliszyk@35222: using a by simp kaliszyk@35222: huffman@35294: subsection {* lemmas for regularisation of ball and bex *} kaliszyk@35222: kaliszyk@35222: lemma ball_reg_eqv: kaliszyk@35222: fixes P :: "'a \ bool" kaliszyk@35222: assumes a: "equivp R" kaliszyk@35222: shows "Ball (Respects R) P = (All P)" kaliszyk@35222: using a kaliszyk@35222: unfolding equivp_def kaliszyk@35222: by (auto simp add: in_respects) kaliszyk@35222: kaliszyk@35222: lemma bex_reg_eqv: kaliszyk@35222: fixes P :: "'a \ bool" kaliszyk@35222: assumes a: "equivp R" kaliszyk@35222: shows "Bex (Respects R) P = (Ex P)" kaliszyk@35222: using a kaliszyk@35222: unfolding equivp_def kaliszyk@35222: by (auto simp add: in_respects) kaliszyk@35222: kaliszyk@35222: lemma ball_reg_right: kaliszyk@35222: assumes a: "\x. R x \ P x \ Q x" kaliszyk@35222: shows "All P \ Ball R Q" kaliszyk@35222: using a by (metis COMBC_def Collect_def Collect_mem_eq) kaliszyk@35222: kaliszyk@35222: lemma bex_reg_left: kaliszyk@35222: assumes a: "\x. R x \ Q x \ P x" kaliszyk@35222: shows "Bex R Q \ Ex P" kaliszyk@35222: using a by (metis COMBC_def Collect_def Collect_mem_eq) kaliszyk@35222: kaliszyk@35222: lemma ball_reg_left: kaliszyk@35222: assumes a: "equivp R" kaliszyk@35222: shows "(\x. (Q x \ P x)) \ Ball (Respects R) Q \ All P" kaliszyk@35222: using a by (metis equivp_reflp in_respects) kaliszyk@35222: kaliszyk@35222: lemma bex_reg_right: kaliszyk@35222: assumes a: "equivp R" kaliszyk@35222: shows "(\x. (Q x \ P x)) \ Ex Q \ Bex (Respects R) P" kaliszyk@35222: using a by (metis equivp_reflp in_respects) kaliszyk@35222: kaliszyk@35222: lemma ball_reg_eqv_range: kaliszyk@35222: fixes P::"'a \ bool" kaliszyk@35222: and x::"'a" kaliszyk@35222: assumes a: "equivp R2" kaliszyk@35222: shows "(Ball (Respects (R1 ===> R2)) (\f. P (f x)) = All (\f. P (f x)))" kaliszyk@35222: apply(rule iffI) kaliszyk@35222: apply(rule allI) kaliszyk@35222: apply(drule_tac x="\y. f x" in bspec) kaliszyk@35222: apply(simp add: in_respects) kaliszyk@35222: apply(rule impI) kaliszyk@35222: using a equivp_reflp_symp_transp[of "R2"] kaliszyk@35222: apply(simp add: reflp_def) kaliszyk@35222: apply(simp) kaliszyk@35222: apply(simp) kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: lemma bex_reg_eqv_range: kaliszyk@35222: assumes a: "equivp R2" kaliszyk@35222: shows "(Bex (Respects (R1 ===> R2)) (\f. P (f x)) = Ex (\f. P (f x)))" kaliszyk@35222: apply(auto) kaliszyk@35222: apply(rule_tac x="\y. f x" in bexI) kaliszyk@35222: apply(simp) kaliszyk@35222: apply(simp add: Respects_def in_respects) kaliszyk@35222: apply(rule impI) kaliszyk@35222: using a equivp_reflp_symp_transp[of "R2"] kaliszyk@35222: apply(simp add: reflp_def) kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: (* Next four lemmas are unused *) kaliszyk@35222: lemma all_reg: kaliszyk@35222: assumes a: "!x :: 'a. (P x --> Q x)" kaliszyk@35222: and b: "All P" kaliszyk@35222: shows "All Q" kaliszyk@35222: using a b by (metis) kaliszyk@35222: kaliszyk@35222: lemma ex_reg: kaliszyk@35222: assumes a: "!x :: 'a. (P x --> Q x)" kaliszyk@35222: and b: "Ex P" kaliszyk@35222: shows "Ex Q" kaliszyk@35222: using a b by metis kaliszyk@35222: kaliszyk@35222: lemma ball_reg: kaliszyk@35222: assumes a: "!x :: 'a. (R x --> P x --> Q x)" kaliszyk@35222: and b: "Ball R P" kaliszyk@35222: shows "Ball R Q" kaliszyk@35222: using a b by (metis COMBC_def Collect_def Collect_mem_eq) kaliszyk@35222: kaliszyk@35222: lemma bex_reg: kaliszyk@35222: assumes a: "!x :: 'a. (R x --> P x --> Q x)" kaliszyk@35222: and b: "Bex R P" kaliszyk@35222: shows "Bex R Q" kaliszyk@35222: using a b by (metis COMBC_def Collect_def Collect_mem_eq) kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: lemma ball_all_comm: kaliszyk@35222: assumes "\y. (\x\P. A x y) \ (\x. B x y)" kaliszyk@35222: shows "(\x\P. \y. A x y) \ (\x. \y. B x y)" kaliszyk@35222: using assms by auto kaliszyk@35222: kaliszyk@35222: lemma bex_ex_comm: kaliszyk@35222: assumes "(\y. \x. A x y) \ (\y. \x\P. B x y)" kaliszyk@35222: shows "(\x. \y. A x y) \ (\x\P. \y. B x y)" kaliszyk@35222: using assms by auto kaliszyk@35222: huffman@35294: subsection {* Bounded abstraction *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: Babs :: "('a \ bool) \ ('a \ 'b) \ 'a \ 'b" kaliszyk@35222: where kaliszyk@35222: "x \ p \ Babs p m x = m x" kaliszyk@35222: kaliszyk@35222: lemma babs_rsp: kaliszyk@35222: assumes q: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and a: "(R1 ===> R2) f g" kaliszyk@35222: shows "(R1 ===> R2) (Babs (Respects R1) f) (Babs (Respects R1) g)" kaliszyk@35222: apply (auto simp add: Babs_def in_respects) kaliszyk@35222: apply (subgoal_tac "x \ Respects R1 \ y \ Respects R1") kaliszyk@35222: using a apply (simp add: Babs_def) kaliszyk@35222: apply (simp add: in_respects) kaliszyk@35222: using Quotient_rel[OF q] kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: lemma babs_prs: kaliszyk@35222: assumes q1: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and q2: "Quotient R2 Abs2 Rep2" kaliszyk@35222: shows "((Rep1 ---> Abs2) (Babs (Respects R1) ((Abs1 ---> Rep2) f))) = f" kaliszyk@35222: apply (rule ext) kaliszyk@35222: apply (simp) kaliszyk@35222: apply (subgoal_tac "Rep1 x \ Respects R1") kaliszyk@35222: apply (simp add: Babs_def Quotient_abs_rep[OF q1] Quotient_abs_rep[OF q2]) kaliszyk@35222: apply (simp add: in_respects Quotient_rel_rep[OF q1]) kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: lemma babs_simp: kaliszyk@35222: assumes q: "Quotient R1 Abs Rep" kaliszyk@35222: shows "((R1 ===> R2) (Babs (Respects R1) f) (Babs (Respects R1) g)) = ((R1 ===> R2) f g)" kaliszyk@35222: apply(rule iffI) kaliszyk@35222: apply(simp_all only: babs_rsp[OF q]) kaliszyk@35222: apply(auto simp add: Babs_def) kaliszyk@35222: apply (subgoal_tac "x \ Respects R1 \ y \ Respects R1") kaliszyk@35222: apply(metis Babs_def) kaliszyk@35222: apply (simp add: in_respects) kaliszyk@35222: using Quotient_rel[OF q] kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: (* If a user proves that a particular functional relation kaliszyk@35222: is an equivalence this may be useful in regularising *) kaliszyk@35222: lemma babs_reg_eqv: kaliszyk@35222: shows "equivp R \ Babs (Respects R) P = P" kaliszyk@35222: by (simp add: expand_fun_eq Babs_def in_respects equivp_reflp) kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: (* 3 lemmas needed for proving repabs_inj *) kaliszyk@35222: lemma ball_rsp: kaliszyk@35222: assumes a: "(R ===> (op =)) f g" kaliszyk@35222: shows "Ball (Respects R) f = Ball (Respects R) g" kaliszyk@35222: using a by (simp add: Ball_def in_respects) kaliszyk@35222: kaliszyk@35222: lemma bex_rsp: kaliszyk@35222: assumes a: "(R ===> (op =)) f g" kaliszyk@35222: shows "(Bex (Respects R) f = Bex (Respects R) g)" kaliszyk@35222: using a by (simp add: Bex_def in_respects) kaliszyk@35222: kaliszyk@35222: lemma bex1_rsp: kaliszyk@35222: assumes a: "(R ===> (op =)) f g" kaliszyk@35222: shows "Ex1 (\x. x \ Respects R \ f x) = Ex1 (\x. x \ Respects R \ g x)" kaliszyk@35222: using a kaliszyk@35222: by (simp add: Ex1_def in_respects) auto kaliszyk@35222: kaliszyk@35222: (* 2 lemmas needed for cleaning of quantifiers *) kaliszyk@35222: lemma all_prs: kaliszyk@35222: assumes a: "Quotient R absf repf" kaliszyk@35222: shows "Ball (Respects R) ((absf ---> id) f) = All f" kaliszyk@35222: using a unfolding Quotient_def Ball_def in_respects fun_map_def id_apply kaliszyk@35222: by metis kaliszyk@35222: kaliszyk@35222: lemma ex_prs: kaliszyk@35222: assumes a: "Quotient R absf repf" kaliszyk@35222: shows "Bex (Respects R) ((absf ---> id) f) = Ex f" kaliszyk@35222: using a unfolding Quotient_def Bex_def in_respects fun_map_def id_apply kaliszyk@35222: by metis kaliszyk@35222: huffman@35294: subsection {* @{text Bex1_rel} quantifier *} kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: Bex1_rel :: "('a \ 'a \ bool) \ ('a \ bool) \ bool" kaliszyk@35222: where kaliszyk@35222: "Bex1_rel R P \ (\x \ Respects R. P x) \ (\x \ Respects R. \y \ Respects R. ((P x \ P y) \ (R x y)))" kaliszyk@35222: kaliszyk@35222: lemma bex1_rel_aux: kaliszyk@35222: "\\xa ya. R xa ya \ x xa = y ya; Bex1_rel R x\ \ Bex1_rel R y" kaliszyk@35222: unfolding Bex1_rel_def kaliszyk@35222: apply (erule conjE)+ kaliszyk@35222: apply (erule bexE) kaliszyk@35222: apply rule kaliszyk@35222: apply (rule_tac x="xa" in bexI) kaliszyk@35222: apply metis kaliszyk@35222: apply metis kaliszyk@35222: apply rule+ kaliszyk@35222: apply (erule_tac x="xaa" in ballE) kaliszyk@35222: prefer 2 kaliszyk@35222: apply (metis) kaliszyk@35222: apply (erule_tac x="ya" in ballE) kaliszyk@35222: prefer 2 kaliszyk@35222: apply (metis) kaliszyk@35222: apply (metis in_respects) kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: lemma bex1_rel_aux2: kaliszyk@35222: "\\xa ya. R xa ya \ x xa = y ya; Bex1_rel R y\ \ Bex1_rel R x" kaliszyk@35222: unfolding Bex1_rel_def kaliszyk@35222: apply (erule conjE)+ kaliszyk@35222: apply (erule bexE) kaliszyk@35222: apply rule kaliszyk@35222: apply (rule_tac x="xa" in bexI) kaliszyk@35222: apply metis kaliszyk@35222: apply metis kaliszyk@35222: apply rule+ kaliszyk@35222: apply (erule_tac x="xaa" in ballE) kaliszyk@35222: prefer 2 kaliszyk@35222: apply (metis) kaliszyk@35222: apply (erule_tac x="ya" in ballE) kaliszyk@35222: prefer 2 kaliszyk@35222: apply (metis) kaliszyk@35222: apply (metis in_respects) kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: lemma bex1_rel_rsp: kaliszyk@35222: assumes a: "Quotient R absf repf" kaliszyk@35222: shows "((R ===> op =) ===> op =) (Bex1_rel R) (Bex1_rel R)" kaliszyk@35222: apply simp kaliszyk@35222: apply clarify kaliszyk@35222: apply rule kaliszyk@35222: apply (simp_all add: bex1_rel_aux bex1_rel_aux2) kaliszyk@35222: apply (erule bex1_rel_aux2) kaliszyk@35222: apply assumption kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: lemma ex1_prs: kaliszyk@35222: assumes a: "Quotient R absf repf" kaliszyk@35222: shows "((absf ---> id) ---> id) (Bex1_rel R) f = Ex1 f" kaliszyk@35222: apply simp kaliszyk@35222: apply (subst Bex1_rel_def) kaliszyk@35222: apply (subst Bex_def) kaliszyk@35222: apply (subst Ex1_def) kaliszyk@35222: apply simp kaliszyk@35222: apply rule kaliszyk@35222: apply (erule conjE)+ kaliszyk@35222: apply (erule_tac exE) kaliszyk@35222: apply (erule conjE) kaliszyk@35222: apply (subgoal_tac "\y. R y y \ f (absf y) \ R x y") kaliszyk@35222: apply (rule_tac x="absf x" in exI) kaliszyk@35222: apply (simp) kaliszyk@35222: apply rule+ kaliszyk@35222: using a unfolding Quotient_def kaliszyk@35222: apply metis kaliszyk@35222: apply rule+ kaliszyk@35222: apply (erule_tac x="x" in ballE) kaliszyk@35222: apply (erule_tac x="y" in ballE) kaliszyk@35222: apply simp kaliszyk@35222: apply (simp add: in_respects) kaliszyk@35222: apply (simp add: in_respects) kaliszyk@35222: apply (erule_tac exE) kaliszyk@35222: apply rule kaliszyk@35222: apply (rule_tac x="repf x" in exI) kaliszyk@35222: apply (simp only: in_respects) kaliszyk@35222: apply rule kaliszyk@35222: apply (metis Quotient_rel_rep[OF a]) kaliszyk@35222: using a unfolding Quotient_def apply (simp) kaliszyk@35222: apply rule+ kaliszyk@35222: using a unfolding Quotient_def in_respects kaliszyk@35222: apply metis kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: lemma bex1_bexeq_reg: "(\!x\Respects R. P x) \ (Bex1_rel R (\x. P x))" kaliszyk@35222: apply (simp add: Ex1_def Bex1_rel_def in_respects) kaliszyk@35222: apply clarify kaliszyk@35222: apply auto kaliszyk@35222: apply (rule bexI) kaliszyk@35222: apply assumption kaliszyk@35222: apply (simp add: in_respects) kaliszyk@35222: apply (simp add: in_respects) kaliszyk@35222: apply auto kaliszyk@35222: done kaliszyk@35222: huffman@35294: subsection {* Various respects and preserve lemmas *} kaliszyk@35222: kaliszyk@35222: lemma quot_rel_rsp: kaliszyk@35222: assumes a: "Quotient R Abs Rep" kaliszyk@35222: shows "(R ===> R ===> op =) R R" kaliszyk@35222: apply(rule fun_rel_id)+ kaliszyk@35222: apply(rule equals_rsp[OF a]) kaliszyk@35222: apply(assumption)+ kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: lemma o_prs: kaliszyk@35222: assumes q1: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and q2: "Quotient R2 Abs2 Rep2" kaliszyk@35222: and q3: "Quotient R3 Abs3 Rep3" kaliszyk@36215: shows "((Abs2 ---> Rep3) ---> (Abs1 ---> Rep2) ---> (Rep1 ---> Abs3)) op \ = op \" kaliszyk@36215: and "(id ---> (Abs1 ---> id) ---> Rep1 ---> id) op \ = op \" kaliszyk@35222: using Quotient_abs_rep[OF q1] Quotient_abs_rep[OF q2] Quotient_abs_rep[OF q3] kaliszyk@36215: unfolding o_def expand_fun_eq by simp_all kaliszyk@35222: kaliszyk@35222: lemma o_rsp: kaliszyk@36215: "((R2 ===> R3) ===> (R1 ===> R2) ===> (R1 ===> R3)) op \ op \" kaliszyk@36215: "(op = ===> (R1 ===> op =) ===> R1 ===> op =) op \ op \" kaliszyk@36215: unfolding fun_rel_def o_def expand_fun_eq by auto kaliszyk@35222: kaliszyk@35222: lemma cond_prs: kaliszyk@35222: assumes a: "Quotient R absf repf" kaliszyk@35222: shows "absf (if a then repf b else repf c) = (if a then b else c)" kaliszyk@35222: using a unfolding Quotient_def by auto kaliszyk@35222: kaliszyk@35222: lemma if_prs: kaliszyk@35222: assumes q: "Quotient R Abs Rep" kaliszyk@36123: shows "(id ---> Rep ---> Rep ---> Abs) If = If" kaliszyk@36123: using Quotient_abs_rep[OF q] kaliszyk@36123: by (auto simp add: expand_fun_eq) kaliszyk@35222: kaliszyk@35222: lemma if_rsp: kaliszyk@35222: assumes q: "Quotient R Abs Rep" kaliszyk@36123: shows "(op = ===> R ===> R ===> R) If If" kaliszyk@36123: by auto kaliszyk@35222: kaliszyk@35222: lemma let_prs: kaliszyk@35222: assumes q1: "Quotient R1 Abs1 Rep1" kaliszyk@35222: and q2: "Quotient R2 Abs2 Rep2" kaliszyk@37049: shows "(Rep2 ---> (Abs2 ---> Rep1) ---> Abs1) Let = Let" kaliszyk@37049: using Quotient_abs_rep[OF q1] Quotient_abs_rep[OF q2] kaliszyk@37049: by (auto simp add: expand_fun_eq) kaliszyk@35222: kaliszyk@35222: lemma let_rsp: kaliszyk@37049: shows "(R1 ===> (R1 ===> R2) ===> R2) Let Let" kaliszyk@37049: by auto kaliszyk@35222: kaliszyk@35222: locale quot_type = kaliszyk@35222: fixes R :: "'a \ 'a \ bool" kaliszyk@35222: and Abs :: "('a \ bool) \ 'b" kaliszyk@35222: and Rep :: "'b \ ('a \ bool)" kaliszyk@35222: assumes equivp: "equivp R" kaliszyk@35222: and rep_prop: "\y. \x. Rep y = R x" kaliszyk@35222: and rep_inverse: "\x. Abs (Rep x) = x" kaliszyk@35222: and abs_inverse: "\x. (Rep (Abs (R x))) = (R x)" kaliszyk@35222: and rep_inject: "\x y. (Rep x = Rep y) = (x = y)" kaliszyk@35222: begin kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: abs::"'a \ 'b" kaliszyk@35222: where kaliszyk@35222: "abs x \ Abs (R x)" kaliszyk@35222: kaliszyk@35222: definition kaliszyk@35222: rep::"'b \ 'a" kaliszyk@35222: where kaliszyk@35222: "rep a = Eps (Rep a)" kaliszyk@35222: kaliszyk@35222: lemma homeier_lem9: kaliszyk@35222: shows "R (Eps (R x)) = R x" kaliszyk@35222: proof - kaliszyk@35222: have a: "R x x" using equivp by (simp add: equivp_reflp_symp_transp reflp_def) kaliszyk@35222: then have "R x (Eps (R x))" by (rule someI) kaliszyk@35222: then show "R (Eps (R x)) = R x" kaliszyk@35222: using equivp unfolding equivp_def by simp kaliszyk@35222: qed kaliszyk@35222: kaliszyk@35222: theorem homeier_thm10: kaliszyk@35222: shows "abs (rep a) = a" kaliszyk@35222: unfolding abs_def rep_def kaliszyk@35222: proof - kaliszyk@35222: from rep_prop kaliszyk@35222: obtain x where eq: "Rep a = R x" by auto kaliszyk@35222: have "Abs (R (Eps (Rep a))) = Abs (R (Eps (R x)))" using eq by simp kaliszyk@35222: also have "\ = Abs (R x)" using homeier_lem9 by simp kaliszyk@35222: also have "\ = Abs (Rep a)" using eq by simp kaliszyk@35222: also have "\ = a" using rep_inverse by simp kaliszyk@35222: finally kaliszyk@35222: show "Abs (R (Eps (Rep a))) = a" by simp kaliszyk@35222: qed kaliszyk@35222: kaliszyk@35222: lemma homeier_lem7: kaliszyk@35222: shows "(R x = R y) = (Abs (R x) = Abs (R y))" (is "?LHS = ?RHS") kaliszyk@35222: proof - kaliszyk@35222: have "?RHS = (Rep (Abs (R x)) = Rep (Abs (R y)))" by (simp add: rep_inject) kaliszyk@35222: also have "\ = ?LHS" by (simp add: abs_inverse) kaliszyk@35222: finally show "?LHS = ?RHS" by simp kaliszyk@35222: qed kaliszyk@35222: kaliszyk@35222: theorem homeier_thm11: kaliszyk@35222: shows "R r r' = (abs r = abs r')" kaliszyk@35222: unfolding abs_def kaliszyk@35222: by (simp only: equivp[simplified equivp_def] homeier_lem7) kaliszyk@35222: kaliszyk@35222: lemma rep_refl: kaliszyk@35222: shows "R (rep a) (rep a)" kaliszyk@35222: unfolding rep_def kaliszyk@35222: by (simp add: equivp[simplified equivp_def]) kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: lemma rep_abs_rsp: kaliszyk@35222: shows "R f (rep (abs g)) = R f g" kaliszyk@35222: and "R (rep (abs g)) f = R g f" kaliszyk@35222: by (simp_all add: homeier_thm10 homeier_thm11) kaliszyk@35222: kaliszyk@35222: lemma Quotient: kaliszyk@35222: shows "Quotient R abs rep" kaliszyk@35222: unfolding Quotient_def kaliszyk@35222: apply(simp add: homeier_thm10) kaliszyk@35222: apply(simp add: rep_refl) kaliszyk@35222: apply(subst homeier_thm11[symmetric]) kaliszyk@35222: apply(simp add: equivp[simplified equivp_def]) kaliszyk@35222: done kaliszyk@35222: kaliszyk@35222: end kaliszyk@35222: huffman@35294: subsection {* ML setup *} kaliszyk@35222: kaliszyk@35222: text {* Auxiliary data for the quotient package *} kaliszyk@35222: kaliszyk@35222: use "~~/src/HOL/Tools/Quotient/quotient_info.ML" kaliszyk@35222: kaliszyk@35222: declare [[map "fun" = (fun_map, fun_rel)]] kaliszyk@35222: kaliszyk@35222: lemmas [quot_thm] = fun_quotient kaliszyk@37049: lemmas [quot_respect] = quot_rel_rsp if_rsp o_rsp let_rsp kaliszyk@37049: lemmas [quot_preserve] = if_prs o_prs let_prs kaliszyk@35222: lemmas [quot_equiv] = identity_equivp kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: text {* Lemmas about simplifying id's. *} kaliszyk@35222: lemmas [id_simps] = kaliszyk@35222: id_def[symmetric] kaliszyk@35222: fun_map_id kaliszyk@35222: id_apply kaliszyk@35222: id_o kaliszyk@35222: o_id kaliszyk@35222: eq_comp_r kaliszyk@35222: kaliszyk@35222: text {* Translation functions for the lifting process. *} kaliszyk@35222: use "~~/src/HOL/Tools/Quotient/quotient_term.ML" kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: text {* Definitions of the quotient types. *} kaliszyk@35222: use "~~/src/HOL/Tools/Quotient/quotient_typ.ML" kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: text {* Definitions for quotient constants. *} kaliszyk@35222: use "~~/src/HOL/Tools/Quotient/quotient_def.ML" kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: text {* kaliszyk@35222: An auxiliary constant for recording some information kaliszyk@35222: about the lifted theorem in a tactic. kaliszyk@35222: *} kaliszyk@35222: definition kaliszyk@36116: "Quot_True (x :: 'a) \ True" kaliszyk@35222: kaliszyk@35222: lemma kaliszyk@35222: shows QT_all: "Quot_True (All P) \ Quot_True P" kaliszyk@35222: and QT_ex: "Quot_True (Ex P) \ Quot_True P" kaliszyk@35222: and QT_ex1: "Quot_True (Ex1 P) \ Quot_True P" kaliszyk@35222: and QT_lam: "Quot_True (\x. P x) \ (\x. Quot_True (P x))" kaliszyk@35222: and QT_ext: "(\x. Quot_True (a x) \ f x = g x) \ (Quot_True a \ f = g)" kaliszyk@35222: by (simp_all add: Quot_True_def ext) kaliszyk@35222: kaliszyk@35222: lemma QT_imp: "Quot_True a \ Quot_True b" kaliszyk@35222: by (simp add: Quot_True_def) kaliszyk@35222: kaliszyk@35222: kaliszyk@35222: text {* Tactics for proving the lifted theorems *} kaliszyk@35222: use "~~/src/HOL/Tools/Quotient/quotient_tacs.ML" kaliszyk@35222: huffman@35294: subsection {* Methods / Interface *} kaliszyk@35222: kaliszyk@35222: method_setup lifting = kaliszyk@35222: {* Attrib.thms >> (fn thms => fn ctxt => SIMPLE_METHOD (HEADGOAL (Quotient_Tacs.lift_tac ctxt thms))) *} kaliszyk@35222: {* lifts theorems to quotient types *} kaliszyk@35222: kaliszyk@35222: method_setup lifting_setup = kaliszyk@35222: {* Attrib.thm >> (fn thms => fn ctxt => SIMPLE_METHOD (HEADGOAL (Quotient_Tacs.procedure_tac ctxt thms))) *} kaliszyk@35222: {* sets up the three goals for the quotient lifting procedure *} kaliszyk@35222: kaliszyk@35222: method_setup regularize = kaliszyk@35222: {* Scan.succeed (fn ctxt => SIMPLE_METHOD (HEADGOAL (Quotient_Tacs.regularize_tac ctxt))) *} kaliszyk@35222: {* proves the regularization goals from the quotient lifting procedure *} kaliszyk@35222: kaliszyk@35222: method_setup injection = kaliszyk@35222: {* Scan.succeed (fn ctxt => SIMPLE_METHOD (HEADGOAL (Quotient_Tacs.all_injection_tac ctxt))) *} kaliszyk@35222: {* proves the rep/abs injection goals from the quotient lifting procedure *} kaliszyk@35222: kaliszyk@35222: method_setup cleaning = kaliszyk@35222: {* Scan.succeed (fn ctxt => SIMPLE_METHOD (HEADGOAL (Quotient_Tacs.clean_tac ctxt))) *} kaliszyk@35222: {* proves the cleaning goals from the quotient lifting procedure *} kaliszyk@35222: kaliszyk@35222: attribute_setup quot_lifted = kaliszyk@35222: {* Scan.succeed Quotient_Tacs.lifted_attrib *} kaliszyk@35222: {* lifts theorems to quotient types *} kaliszyk@35222: kaliszyk@35222: no_notation kaliszyk@35222: rel_conj (infixr "OOO" 75) and kaliszyk@35222: fun_map (infixr "--->" 55) and kaliszyk@35222: fun_rel (infixr "===>" 55) kaliszyk@35222: kaliszyk@35222: end kaliszyk@35222: