(* * COMP4161 Assignment 3. *) theory a3 imports AutoCorres "~~/src/HOL/Number_Theory/Number_Theory" 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 *) lemma unique_prefix_add: "\unique_prefix m1; unique_prefix m2; \xs \ dom m1. \ys \ dom m2. \ xs < ys \ \ ys < xs \ \ unique_prefix (m1 ++ m2)" oops lemma unique_prefix_code_map[simp]: "unique_prefix (map_of (code_map t))" oops lemma build_tree_Branch: "2 \ length ts \ \l r. build_tree ts = Branch l r" oops (* Q1 j): *) 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" sorry (* TODO *) (*******************************************************************) (* C Verification *) (*******************************************************************) (* Parse the C file into SIMPL. *) install_C_file "prime2.c" (* Convert the SIMPL into monadic representation. *) autocorres [unsigned_word_abs=is_prime_2, ts_force nondet=is_prime_2] "prime2.c" (*******************************************************************) section "Primality modulo 2" context prime2 begin thm is_prime_2'_def (* Q2 a): Loop invariant for "is_prime_2". *) definition is_prime_inv :: "nat \ nat \ bool" where "is_prime_inv i n \ True (*TODO*)" (* Q2 b): Measure function for "is_prime_2". Must be strictly decreasing * for each loop iteration. *) definition is_prime_measure :: "nat \ nat \ nat" where "is_prime_measure i n \ undefined" (*TODO*) (* Q2 c1): A prime is either 2 or an odd number *) lemma prime_2_or_odd: "prime n \ n = 2 \ n mod 2 = Suc 0" sorry (* TODO *) (* Q2 c2): The loop invariant holds coming into the loop. *) lemma is_prime_precond_implies_inv: "True" sorry (*TODO*) (* Q2 c3): The loop invariant holds for each loop iteration. *) lemma is_prime_body_obeys_inv: "True" sorry (*TODO*) (* Q2 c4): The loop measure decrements each loop iteration. *) lemma is_prime_body_obeys_measure: "\ is_prime_inv i n; n mod i \ 0 \ \ is_prime_measure i n > is_prime_measure (i + 2) n" sorry (*TODO*) (* Q2 c5): The loop invariant implies there is no overflow. *) lemma is_prime_body_implies_no_overflow: "\ is_prime_inv i n; n mod i \ 0\ \ i + 2 \ UINT_MAX" sorry (* Q2 c6): The loop invariant implies the post-condition. *) lemma is_prime_inv_implies_postcondition: "True" sorry (*TODO*) (* * Q2 d): Show that "is_prime' n" is correct. * * AutoCorres has applied "word abstraction" to this function, * meaning that you are able to reason using "nats" instead of * "word32" data types, at the price of having to reason that * your values don't overflow UINT_MAX. *) lemma is_prime_correct: "\\s. n \ UINT_MAX \ is_prime_2' n \\r s. r = (if prime n then 1 else 0) \!" (* Unfold the program body. *) apply (unfold is_prime_2'_def) (* Annotate the loop with an invariant and measure. *) apply (subst whileLoop_add_inv [where I="\i s. is_prime_inv i n" and M="\(i, s). is_prime_measure i n" ]) (* * Run "wp" to generate verification conditions. * * The resulting subgoals are: * 1. The loop body obeys the invariant, causes the measure to decrease, and does not lead to overflow; * 2. The invariant implies the post-condition of the function; and * 3. The pre-condition of the function implies the invariant. * * You will need to run "apply wp" more times to convert Hoare-triples * into standard Isabelle goals. *) apply wp sorry (*TODO*) end end