theory Demo09 imports Main begin section \Typedef\ text \Redefinition of sets, we use capital letters to distinguish it from existing set-type.\ typedef 'a SET = "{ f :: 'a \ bool. True}" by auto print_theorems term "Rep_SET :: 'a SET \ ('a \ bool)" term "Abs_SET :: ('a \ bool) \ 'a SET" definition EMPTY :: "'a SET" where "EMPTY = Abs_SET (\ _. False)" definition ELEM :: "'a \ 'a SET \ bool" where "ELEM x A = Rep_SET A x" definition UNION :: "'a SET \ 'a SET \ 'a SET" where "UNION A B = Abs_SET (\ x. Rep_SET A x \ Rep_SET B x)" lemma UNION: "ELEM x (UNION A B) \ ELEM x A \ ELEM x B" unfolding UNION_def ELEM_def apply (subst Abs_SET_inverse) by auto thm Abs_SET_inverse text \Example Type-Definitions\ typedef 'a ty1 = "{ f :: 'a \ nat . True}" by auto typedef 'a ty2 = "{ f :: 'a \ nat . finite {x. f x > 0}}" by (intro exI[of _ "\ _ . 0"], auto) typedef 'a ty3 = "{ f :: nat \ 'a . True}" by auto typedef 'a ty4 = "{ (n, f :: nat \ 'a) . (\ i. i < n \ f i = undefined) }" by auto text \Example: Integers\ typedef INTEGER = "{ bn. case bn of (b,n :: nat) \ n = 0 \ b}" by auto print_theorems thm Rep_INTEGER_inverse thm Rep_INTEGER thm Abs_INTEGER_inverse definition ZERO :: INTEGER where "ZERO = Abs_INTEGER (True, 0)" text \define addition on representative type\ fun add_integer :: "bool \ nat \ bool \ nat \ bool \ nat" where "add_integer (True,n) (True,m) = (True, n+m)" | "add_integer (False,n) (False,m) = (False, n+m)" | "add_integer (True,n) (False,m) = (if m \ n then (True, n - m) else (False, m - n))" | "add_integer (False,n) (True,m) = (if n \ m then (True, m - n) else (False, n - m))" text \and lift this to addition on abstract type\ definition ADD :: "INTEGER \ INTEGER \ INTEGER" where "ADD x y = Abs_INTEGER (add_integer (Rep_INTEGER x) (Rep_INTEGER y))" text \tedious reasoning via conversion functions\ lemma "ADD x ZERO = x" unfolding ADD_def ZERO_def apply (cases "Rep_INTEGER x", auto) thm Abs_INTEGER_inverse apply (simp add: Abs_INTEGER_inverse) proof - fix b n assume *: "Rep_INTEGER x = (b,n)" show "Abs_INTEGER (add_integer (b, n) (True, 0)) = x" proof (cases b) case True thus ?thesis using * apply auto by (metis Rep_INTEGER_inverse) thm Rep_INTEGER_inverse next case False with * have n: "n > 0" using Rep_INTEGER[of x] by auto thus ?thesis using * False apply auto by (metis Rep_INTEGER_inverse) qed qed section \Lifting and Transfer Package\ subsection \Example: Integers\ setup_lifting type_definition_INTEGER lift_definition Zero :: INTEGER is "(True,0)" by auto lift_definition Add :: "INTEGER \ INTEGER \ INTEGER" is add_integer proof (goal_cases) case (1 bn1 bn2) thus ?case by (cases "(bn1,bn2)" rule: add_integer.cases, auto) qed lemma "Add x Zero = x" proof (transfer, goal_cases) case (1 bn) thus ?case by (cases "(bn, (True,0 :: nat))" rule: add_integer.cases, auto) qed lift_definition Negate :: "INTEGER \ INTEGER" is "\ (b,n). if n = 0 then (b,0) else (\ b, n)" by (auto split: prod.splits) lemma "Negate Zero = Zero" by (transfer, auto) lemma "Negate (Negate x) = x" by (transfer, auto split: if_splits) lemma "Add (Negate x) x = Zero" proof (transfer, goal_cases) case (1 bn) then obtain b n where bn: "bn = (b,n)" and cond: "n = 0 \ b" by auto show ?case unfolding bn split using cond by (cases b, auto) qed subsection \Implementation of Binary Search Trees from Previous Week\ datatype 'a tree = Leaf | Node "'a tree" 'a "'a tree" fun set_t :: "'a tree \ 'a set" where "set_t Leaf = {}" | "set_t (Node l x r) = set_t l \ {x} \ set_t r" inductive ordered :: "'a :: linorder tree \ bool" where oLeaf: "ordered Leaf" | oNode: "ordered l \ ordered r \ Ball (set_t l) (\ y. y < x) \ Ball (set_t r) (\ y. y > x) \ ordered (Node l x r)" fun member:: "'a :: linorder \ 'a tree \ bool" where "member x Leaf = False" | "member y (Node l x r) = (if x = y then True else if y < x then member y l else member y r)" lemma member_correct: "ordered t \ member x t = (x \ set_t t)" by (induction rule: ordered.induct, auto) fun insert_t :: "'a :: linorder \ 'a tree \ 'a tree" where "insert_t y Leaf = Node Leaf y Leaf" | "insert_t y (Node l x r) = (if x = y then Node l x r else if y < x then Node (insert_t y l) x r else Node l x (insert_t y r))" lemma set_insert_t[simp]: "set_t (insert_t x t) = insert x (set_t t)" by (induct t, auto) lemma ordered_insert_t: "ordered t \ ordered (insert_t x t)" by (induction rule: ordered.induct, auto intro!: oNode oLeaf) fun delete_right :: "'a :: linorder tree \ 'a tree \ 'a" where "delete_right (Node l x Leaf) = (l, x)" | "delete_right (Node l x r) = (case delete_right r of (r', y) \ (Node l x r', y))" fun delete :: "'a :: linorder \ 'a tree \ 'a tree" where "delete x Leaf = Leaf" | "delete x (Node l y r) = (if x < y then Node (delete x l) y r else if x > y then Node l y (delete x r) else if l = Leaf then r else case delete_right l of (l',z) \ Node l' z r)" lemma delete_right: "ordered t \ t \ Leaf \ delete_right t = (t', x) \ ordered t' \ set_t t = insert x (set_t t') \ Ball (set_t t') (\ y. y < x)" proof (induction t arbitrary: t' x rule: ordered.induct) case (oNode l r x t' y) thus ?case proof (cases r) case Leaf thus ?thesis using oNode by auto next case Node from oNode.prems[unfolded Node, simplified, folded Node] obtain r' where dr: "delete_right r = (r',y)" and t': "t' = Node l x r'" by (cases "delete_right r", auto) from Node have r: "r \ Leaf" by auto from oNode.IH(2)[OF r dr] oNode.hyps show ?thesis unfolding t' by (auto intro: ordered.intros) qed qed auto lemma delete: "ordered t \ ordered (delete x t) \ set_t (delete x t) = set_t t - {x}" proof (induction t rule: ordered.induct) case (oNode l r y) consider (LT) "x < y" | (EQ) "x = y" "l = Leaf" | (EQ2) "x = y" "l \ Leaf" | (GT) "x > y" by fastforce then show ?case proof cases case LT hence id: "delete x (Node l y r) = Node (delete x l) y r" by simp from oNode.IH(1) show ?thesis using oNode.hyps LT unfolding id by (auto intro: ordered.intros) next case EQ then show ?thesis using oNode.hyps by auto next case EQ2 obtain l' z where del: "delete_right l = (l',z)" by force from del EQ2 have id: "delete x (Node l y r) = Node l' z r" by auto from delete_right[OF _ EQ2(2) del] oNode.hyps have "ordered l' \ set_t l = insert z (set_t l') \ (\y\set_t l'. y < z)" by auto with oNode.hyps EQ2 show ?thesis unfolding id by (auto intro!: ordered.intros) next case GT hence id: "delete x (Node l y r) = Node l y (delete x r)" by auto from oNode.IH(2) show ?thesis using oNode.hyps GT unfolding id by (auto intro: ordered.intros) qed qed (auto intro: ordered.intros) subsection \Example: Type of Ordered Binary Trees\ (* (overloaded) is required since type-variable has class-constraint *) typedef (overloaded) ('a :: linorder) otree = "{t :: 'a tree. ordered t}" by (intro exI[of _ Leaf], auto intro: ordered.intros) setup_lifting type_definition_otree lift_definition empty_o :: "('a :: linorder) otree" is Leaf by (auto intro: ordered.intros) lift_definition insert_o :: "'a :: linorder \ 'a otree \ 'a otree" is insert_t by (rule ordered_insert_t) lift_definition delete_o :: "'a :: linorder \ 'a otree \ 'a otree" is delete using delete by blast lift_definition member_o :: "'a :: linorder \ 'a otree \ bool" is member . lift_definition set_o :: "'a :: linorder otree \ 'a set" is set_t . lemma empty_o: "set_o empty_o = {}" apply transfer by auto lemma insert_o: "set_o (insert_o x t) = insert x (set_o t)" apply transfer using set_insert_t by auto lemma delete_o: "set_o (delete_o x t) = (set_o t) - {x}" apply transfer using delete by auto lemma member_o: "member_o x t = (x \ set_o t)" apply transfer using member_correct by auto end