theory Inductive_Quotients imports Main begin subsection \Restricted quotient predicate\ definition "Quotient' X R Abs Rep T \ (\a. \b\X. T a b \ Abs a = b) \ (\b\X. T (Rep b) b) \ (\x y. R x y \ (Abs x \ X \ Abs y \ X)) \ (\x y. Abs x \ X \ R x y = (T x (Abs x) \ T y (Abs y) \ Abs x = Abs y))" lemma Quotient_Quotient': assumes "Quotient R Abs Rep T" shows "Quotient' X R Abs Rep T" using assms unfolding Quotient_alt_def Quotient'_def by simp lemma Quotient'_UNIV: assumes "Quotient' UNIV R Abs Rep T" shows "Quotient R Abs Rep T" using assms unfolding Quotient_alt_def Quotient'_def by simp lemma Quotient'_Union: assumes "\X\M. Quotient' X R Abs Rep T" shows "Quotient' (\M) R Abs Rep T" using assms unfolding Quotient'_def by fast lemma Quotient'_union: assumes "Quotient' X R Abs Rep T" and "Quotient' Y R Abs Rep T" shows "Quotient' (X \ Y) R Abs Rep T" using assms unfolding Quotient'_def by fast (*TODO: There is probably a nicer (or more general) way to express this idea.*) lemma Quotient'_inject: assumes "Quotient' X (BNF_Def.vimage2p g g R) (f' \ Abs \ g) (g' \ Rep \ f) (BNF_Def.vimage2p g f T)" and "\a. \x\X. T a (f x) \ (\y. a = g y)" and "f \ f' \ Abs \ g = Abs \ g" and "g \ g' \ Rep \ f = Rep \ f" and "\a b. \x\X. R a b \ (Abs a = f x \ Abs b = f x) \ (\y z. a = g y \ b = g z)" shows "Quotient' (f ` X) R Abs Rep T" using assms unfolding Quotient'_def BNF_Def.vimage2p_def comp_def (*SLOW!*) apply (safe) apply (metis) apply (metis) apply (smt image_iff) apply (smt image_iff) apply (smt) apply (smt) apply (smt) apply (metis) done text \BNF example — a refined version of @{thm fun_quotient}:\ lemma Quotient'_fun: assumes "Quotient R1 Abs1 Rep1 T1" and "Quotient' X R2 Abs2 Rep2 T2" shows "Quotient' {f. range f \ X} (rel_fun R1 R2) (map_fun Rep1 Abs2) (map_fun Abs1 Rep2) (rel_fun T1 T2)" using assms unfolding Quotient_alt_def2 Quotient'_def rel_fun_def fun_eq_iff map_fun_apply apply (safe) apply (metis UNIV_I image_subset_iff) apply (metis UNIV_I image_subset_iff) apply (metis image_subset_iff) apply (metis image_subset_iff) apply (metis UNIV_I image_subset_iff) apply (metis UNIV_I image_subset_iff) apply (metis UNIV_I image_subset_iff) apply (smt UNIV_I image_subset_iff) done subsection \Example\ datatype 'a T = L | N "'a \ 'a T" inductive rel_T :: "('a \ 'b \ bool) \ 'a T \ 'b T \ bool" for R where "rel_T R L L" | "rel_fun R (rel_T R) f g \ rel_T R (N f) (N g)" primrec map_T :: "('a \ 'b) \ 'b T \ 'a T" where "map_T u L = L" | "map_T u (N f) = N (map_T u o f o u)" definition "apply_T_ctors S = {L} \ {N f | f. range f \ S}" lemma mono_apply_T_ctors: "mono apply_T_ctors" unfolding apply_T_ctors_def by (auto intro: monoI) lemma lfp_apply_T_ctors: "lfp apply_T_ctors = UNIV" proof - have "UNIV \ lfp apply_T_ctors" proof (rule lfp_greatest) fix S :: "'b T set" have closed: "x \ S" if ctors: "L \ S" "{N f | f. range f \ S} \ S" for x proof (induction x) case L show ?case using ctors by blast next case (N x) then show ?case using ctors by blast qed assume "apply_T_ctors S \ S" then show "UNIV \ S" unfolding apply_T_ctors_def using closed by blast qed then show ?thesis by blast qed lemma Quotient'_T: assumes inner: "Quotient R Abs Rep T" shows "Quotient' UNIV (rel_T R) (map_T Rep) (map_T Abs) (rel_T T)" (is "?Q UNIV") proof - have "?Q (lfp apply_T_ctors)" using mono_apply_T_ctors proof (rule lfp_ordinal_induct_set) fix S assume IH: "?Q S" have Q_L: "?Q {L}" unfolding Quotient'_def by (fastforce elim: rel_T.cases intro: rel_T.intros) have "inj N" by (auto intro: injI) have rel_T_R: "BNF_Def.vimage2p N N (rel_T R) = rel_fun R (rel_T R)" unfolding BNF_Def.vimage2p_def by (blast elim: rel_T.cases intro: rel_T.intros) have map_T_Rep: "inv N \ map_T Rep \ N = map_fun Rep (map_T Rep)" by (simp add: inv_f_f[OF \inj N\] comp_def map_fun_def[abs_def]) have map_T_Rep': "N \ inv N \ map_T Rep \ N = map_T Rep \ N" by (simp add: inv_f_f[OF \inj N\] comp_def map_fun_def[abs_def]) have map_T_Abs: "inv N \ map_T Abs \ N = map_fun Abs (map_T Abs)" by (simp add: inv_f_f[OF \inj N\] comp_def map_fun_def[abs_def]) have map_T_Abs': "N \ inv N \ map_T Abs \ N = map_T Abs \ N" by (simp add: inv_f_f[OF \inj N\] comp_def map_fun_def[abs_def]) have rel_T_T: "BNF_Def.vimage2p N N (rel_T T) = rel_fun T (rel_T T)" unfolding BNF_Def.vimage2p_def by (blast elim: rel_T.cases intro: rel_T.intros) have "Quotient' {f. range f \ S} (BNF_Def.vimage2p N N (rel_T R)) (inv N \ map_T Rep \ N) (inv N \ map_T Abs \ N) (BNF_Def.vimage2p N N (rel_T T))" unfolding rel_T_R map_T_Rep map_T_Abs rel_T_T using inner IH by (rule Quotient'_fun) then have "?Q (N ` {f. range f \ S})" using map_T_Rep' map_T_Abs' by (auto intro!: Quotient'_inject elim: rel_T.cases) then have Q_N: "?Q {N f | f. range f \ S}" unfolding setcompr_eq_image . from Q_L Q_N show "?Q (apply_T_ctors S)" unfolding apply_T_ctors_def by (rule Quotient'_union)+ next (*TODO: Derived induction rule for Quotient' (lfp _) *) fix M assume "\S\M. ?Q S" then show "?Q (\M)" by (rule Quotient'_Union) qed then show ?thesis unfolding lfp_apply_T_ctors . qed corollary Quotient_T [quot_map]: assumes "Quotient R Abs Rep T" shows "Quotient (rel_T R) (map_T Rep) (map_T Abs) (rel_T T)" using assms Quotient'_T by (blast intro: Quotient'_UNIV) end