theory a3 imports AutoCorres begin (*---------------------------------------------------------*) (*---------------------------------------------------------*) section \ Induction (25 marks) \ fun mystery_f :: "nat \ string \ string" where "mystery_f 0 _ = []" | "mystery_f (Suc 0) a = a" | "mystery_f k a = (if k mod 2 = 0 then mystery_f (k div 2) (a @ a) else mystery_f (k div 2) (a @ a) @ a)" (* (a) Explain in one sentence or two what this function is doing. Justify your answer with a few representative examples. *) (*TODO*) (* (b) Prove the following properties: *) lemma "(mystery_f n []) = TODO" (*you may reformulate the lemma slightly*) (*TODO*) sorry lemma length_mystery_f : "length (mystery_f n s) = TODO" (*TODO*) sorry lemma "mystery_f (n+m) s = TODO" (*TODO*) sorry (*---*) definition mystery_g :: "string \ nat \ string \ string option" where "mystery_g c k s = (if size c \ 1 \ size s > k then None else Some (mystery_f (k - size s) c @ s))" (* (c) Explain in one sentence or two what this function is doing. Justify your answer with a few representative examples. Try for instance @{term "mystery_g ''0'' 8 ''101''"}.*) (*TODO*) (* (d) Prove the following lemma: *) lemma mystery_g_length: "mystery_g c k s = Some xs \ length xs = k" (*TODO*) sorry (* (e) Prove the following lemma: *) lemma mystery_g_suffix: "mystery_g [c] k s = Some xs \ \zs. xs = zs @ s \ (k=length s \ set zs = {c})" (*TODO*) sorry (*---------------------------------------------------------*) (*---------------------------------------------------------*) section \ C verification: doubly-linked list (40 marks) \ (* Installing the C file and converting it using the AutoCorress tool *) install_C_file "dlist.c" autocorres [unsigned_word_abs=f, ts_force nondet=f] "dlist.c" term "is_valid_node_C p" (* Definition of *path*: (path vld hp nxt p l q) says that you start from pointer p, and "follow" the function nxt, adding each encountered pointer to the list l, until you reach the pointer q, and that all encountered pointers are valid nodes according to the predicate vld, are not NULL, and not q: l=[ p , p1 , p2 , q ] \ \ \ \ []\[]\[]\[] nxt nxt nxt *) primrec path :: "(node_C ptr \ bool) \ (* valid predicate *) (node_C ptr \ node_C) \ (* the heap *) (node_C \ node_C ptr) \ (* the function that maps to next element, i.e. the field of the node *) node_C ptr \ (* the starting pointer *) node_C ptr list \ (* the list of traversed pointers *) node_C ptr \ (* the end pointer *) bool" where "path vld hp nxt p [] q = (p = q)" | "path vld hp nxt p (x#xs) q = (p \ q \ vld p \ p \ NULL \ p=x \ path vld hp nxt (nxt (hp p)) xs q)" (* Definition of *is_dlist*: (is_dlist vld hp p q xs) is True if we have a valid doubly-linked list starting from p and ending in q: xs=[ p , p1, p2, q ] \ \ \ \ NULL\[]\[]\[]\[]\ NULL *) definition "is_dlist vld hp p xs q \ path vld hp next_C p xs NULL \ path vld hp prev_C q (rev xs) NULL" (* (a) Start proof of insert_after_inserts *) (* TODO: start the proof in question (d) below, just to give you a feeling of what the goal looks like and why we need all the helper lemmas *) (* (b) Prove path_upd *) lemma path_upd: "x \ set xs \ path vld (hp (x := y)) n p xs q = path vld hp n p xs q" (*TODO*) sorry (* (c) Prove path_in, path_unique, path_appendD, path_hd_not_in_tl, path_append_last *) lemma path_in: "\path vld hp n p xs q; xs \ []\ \ p \ set xs" (*TODO*) sorry lemma path_unique: "\ path vld hp n p xs q; path vld hp n p ys q \ \ xs = ys" (*TODO*) sorry lemma path_appendD: "path vld hp n p (xs@ys) q \ \r. path vld hp n p xs r \ path vld hp n r ys q" (*TODO*) sorry lemma path_hd_not_in_tl: "path vld hp n (n (hp p)) xs q \ p \ set xs" (*TODO*) sorry lemma path_append_last: "path vld hp n p (xs@ys) q = (path vld hp n p xs (if ys = [] then q else hd ys) \ path vld hp n (if ys = [] then q else hd ys) ys q \ set xs \ set ys = {} \ q \ set xs)" (*TODO*) sorry (* (d) Finish proof of correctness insert_after_inserts *) definition insert_pre where "insert_pre p xs q nd s= (xs\[] \ is_dlist (is_valid_node_C s) (heap_node_C s) p xs q \ nd \ NULL \ is_valid_node_C s nd \ nd \ set xs )" definition insert_post where "insert_post p xs nd s= is_dlist (is_valid_node_C s) (heap_node_C s) p (xs @ [nd]) nd " context dlist begin lemma insert_after_inserts: "\\ s. insert_pre p xs q nd s\ insert_after' nd q \\_ s. insert_post p xs nd s\" (* TODO *) sorry end (*---------------------------------------------------------*) (*---------------------------------------------------------*) section \ C verification: invariant (35 marks) \ (* (a) What is the invariant for the loop? Trace a few example computations in your favourite programming language to discover the relationship between the variables. *) (*TODO*) (* (b) What is a variant for the loop that guarantees that the loop terminates? *) (*TODO*) (* (c) State the property as a (total correctness) Hoare triple and prove it.*) context dlist begin lemma f_correct: "\\_. a \ SQ_MAX \ f' a \\r _. (0 < a \ (r - 1) * (r - 1) < a \ a \ r*r) \ (a = 0 \ r = 0) \!" apply (unfold f'_def) apply (subst whileLoop_add_inv [where I = "\(k, m, n) _. TODO" and (* the invariant*) M = "\((k, m, n), _). TODO"]) (*the variant *) (*TODO: finish proof*) sorry end end