(* * COMP4161 Assignment 3. *) theory a3 imports AutoCorres.AutoCorres "HOL-Library.Prefix_Order" begin section "Huffman Code" (* The template for this question contains hints in the form of lemmas that are not one of the direct questions a)-j). They are marked with "oops". You can, but do not have to prove these lemma. There is more than one way to arrive at a correct proof. The lemmas marked with sorry and TODO are the ones you should prove unchanged for Q1. In Q2 you are allowed to tune the lemma statements. *) type_synonym 'a freq_list = "('a \ int) list" (* Q1 a): TODO *) primrec add_one :: "'a \ 'a freq_list \ 'a freq_list" where "add_one c [] = undefined" (* TODO *) primrec freq_of :: "'a list \ 'a freq_list" where "freq_of [] = undefined" (* TODO *) value "freq_of ''abcdaa''" lemma fst_set_add_one: "fst ` set (add_one x xs) = {x} \ fst ` set xs" oops (* Q1 b): *) lemma distinct_freq[simp]: "distinct (map fst (freq_of cs))" sorry (* TODO *) datatype 'a htree = Leaf 'a int | Branch "'a htree" "'a htree" primrec weight :: "'a htree \ int" where "weight (Leaf _ w) = w" | "weight (Branch l r) = weight l + weight r" fun build_tree :: "'a htree list \ 'a htree" where "build_tree [] = Leaf undefined 0" | "build_tree [t] = t" | "build_tree (t1 # t2 # cs) = build_tree (insort_key weight (Branch t1 t2) cs)" definition huffman_tree :: "'a freq_list \ 'a htree" where "huffman_tree = build_tree o map (\(c,w). Leaf c w) o sort_key snd" definition "some_tree = huffman_tree (freq_of ''abcdaa'')" value some_tree type_synonym code = "bool list" fun add_bit :: "bool \ 'a \ code \ 'a \ code" where "add_bit b (c, code) = (c, b # code)" primrec code_list :: "'a htree \ ('a \ code) list" where "code_list (Leaf c _) = [(c,[])]" | "code_list (Branch l r) = map (add_bit False) (code_list l) @ map (add_bit True) (code_list r)" definition code_map :: "'a htree \ (code \ 'a) list" where "code_map tree = map (\(a,b). (b,a)) (code_list tree)" value "code_list some_tree" value "code_map some_tree" (* Q1 c): TODO *) definition encoder :: "('a \ code option) \ 'a list \ code" where "encoder mp xs = undefined" (* TODO *) fun decoder :: "(code \ 'a option) \ code \ code \ 'a list" where "decoder mp acs [] = []" | "decoder mp acs (c#cs) = (if mp (acs@[c]) \ None then the (mp (acs@[c])) # decoder mp [] cs else decoder mp (acs @ [c]) cs)" definition unique_prefix :: "(code \ 'a option) \ bool" where "unique_prefix cm = (\xs\dom cm. \ys\dom cm. \ ys < xs)" definition is_inv :: "('a \ 'b option) \ ('b \ 'a option) \ bool" where "is_inv mp mp' = (\x y. mp x = Some y \ mp' y = Some x)" lemma unique_prefixD: "\ unique_prefix m; m xs = Some y; m xs' = Some y'; xs = xs' @ xs'' \ \ xs'' = []" oops lemma decoder_step: "\unique_prefix mp'; mp' ys' = None; mp' (ys' @ ys) = Some x\ \ decoder mp' ys' (ys @ zs) = x # decoder mp' [] zs" oops (* Q1 d): *) lemma decoder: "\ is_inv mp mp'; unique_prefix mp'; set xs \ dom mp; [] \ dom mp' \ \ decoder mp' [] (encoder mp xs) = xs" sorry (* TODO *) (* Q1 e): *) lemma is_inv_map_of: "\ distinct (map snd xs); distinct (map fst xs) \ \ is_inv (map_of xs) (map_of (map (\(a,b). (b,a)) xs))" sorry (* TODO *) (* Q1 f): *) primrec letters_of :: "'a htree \ 'a set" where "letters_of (Leaf c _) = undefined" (* TODO: complete *) (* Q1 g): *) fun distinct_tree :: "'a htree \ bool" where "distinct_tree (Leaf _ _) = undefined" (* TODO: complete *) fun distinct_forest :: "'a htree list \ bool" where "distinct_forest [] = True" | "distinct_forest (t#ts) = (distinct_tree t \ distinct_forest ts \ letters_of t \ \ (set (map letters_of ts)) = {})" lemma fst_code_list: "fst ` set (code_list t) = letters_of t" oops (* Q1 h): *) lemma distinct_fst_code_list[simp]: "distinct_tree t \ distinct (map fst (code_list t))" sorry (* TODO *) lemma distinct_forest_insort: "distinct_forest (insort_key f t ts) = (distinct_tree t \ distinct_forest ts \ letters_of t \ \ (set (map letters_of ts)) = {})" oops lemma distinct_build_tree: "distinct_forest ts \ distinct_tree (build_tree ts)" oops lemma distinct_insort_map: "distinct (map g (insort_key f x xs)) = (g x \ g ` set xs \ distinct (map g xs))" oops (* Q1 i): *) lemma distinct_huffman[simp]: "distinct (map fst fs) \ distinct_tree (huffman_tree fs)" sorry (* TODO *) (* If you're curious, this would be the overall correctness statement. You do not need to prove this one. theorem huffman_decoder: "\set xs \ set ys; tree = huffman_tree (freq_of ys); 2 \ length (freq_of ys) \ \ decoder (map_of (code_map tree)) [] (encoder (map_of (code_list tree)) xs) = xs" oops *) (* ------------------------------------------------------------------------------------ *) declare [[syntax_ambiguity_warning = false]] definition "LEN = 1000" declare LEN_def[simp] external_file "stack.c" install_C_file "stack.c" autocorres "stack.c" context stack begin thm is_empty'_def thm has_capacity'_def thm push'_def thm pop'_def thm sum'_def primrec stack_from :: "machine_word list \ machine_word \ lifted_globals \ bool" where "stack_from [] n s = (n = -1 )" | "stack_from (x # xs) n s = (n < LEN \ content_'' s.[unat n] = x \ stack_from xs (n - 1) s)" definition is_stack where "is_stack xs s \ stack_from xs (top_'' s) s" (* Q2 a) *) lemma is_stack_Nil_top[simp]: "is_stack [] s = (top_'' s = -1)" sorry (* TODO *) (* Q2 b) *) lemma is_stack_Nil_is_empty: "is_stack [] s = (is_empty' s = 1)" sorry (* TODO *) (* Q2 c) *) lemma stack_from_neg[simp]: "stack_from xs (- 1) s = (xs = [])" sorry (* TODO *) (* Q2 d) *) lemma is_stack_single: "is_stack [x] s = (top_'' s = 0 \ content_'' s.[0] = x)" sorry (* TODO *) (* Q2 e) *) lemma is_stack_Cons[simp]: "is_stack (x # xs) s = (top_'' s < LEN \ content_'' s.[unat (top_'' s)] = x \ stack_from xs (top_'' s - 1) s)" sorry (* TODO *) (* Q2 f) *) lemma stack_from_top_upd[simp]: "stack_from xs n (s\top_'' := t\) = stack_from xs n s" sorry (* TODO *) (* Helper lemma -- you can prove this one or state your own *) lemma stack_from_top_and_array_upd': "\ \i \ unat n. a.[i] = content_'' s.[i] \ \ stack_from xs n (s\top_'' := t, content_'' := a\) = stack_from xs n s" oops (* Q2 g) *) lemma stack_from_top_and_array_upd[simp]: "unat (n + 1) < LEN \ stack_from xs n (s\top_'' := n+1, content_'' := Arrays.update (content_'' s) (unat (n+1)) x\) = stack_from xs n s" sorry (* TODO *) (* Q2 h) *) lemma pop_correct_partial: "\ \s. is_stack (x#xs) s \ pop' \ \rv s. rv = x \ TODO \" sorry (* TODO *) (* Q2 i) *) lemma pop_correct_total: "\ \s. TODO \ pop' \ \rv s. TODO \!" sorry (* TODO *) (* Q2 j) *) lemma push_correct_total: "\ \s. TODO \ push' x \ \_ s. TODO \!" supply word_less_nat_alt[simp] sorry (* TODO *) (* Q2 k) *) lemma sum_correct_partial: "\ \s. is_stack xs s \ sum' \ \rv s. is_stack [] s \ rv = sum_list xs \" unfolding sum'_def apply (subst whileLoop_add_inv[where I="TODO"]) sorry (* TODO *) end end