chapter \Exercise Sheet -- Week 6\ theory Exercise06 imports Complex_Main (* imports real numbers and exponentiation with real exponent: powr *) begin section \Exercise 1 -- 2 points\ text \The aim is to prove @{term "sqrt 2 \ \"}.\ text \To this end, first develop a variant of the proof that was given in Demo06 in the lecture. Here, the difference is that we consider the real numbers and identify the rational numbers as a specific set of real numbers: @{term \}.\ lemma sqrt_2_irrational_main: "\ (\ (q :: real) \ \. q^2 = 2)" sorry text \Afterwards show the desired lemma\ lemma sqrt_2_irrational[intro]: "sqrt 2 \ \" sorry section \Exercise 2 -- 3 points\ text \Show that there exists two irrational numbers $x$ and $y$ such that $x^y$ is rational. To this end, there is a nice non-constructive proof: Choose $y = \sqrt{2}$, and choose $x = \sqrt{2}$ or $\sqrt{2}^{\sqrt{2}}$, depending on whether the latter number is rational or not. \ lemma power_of_two_irrationals_is_rational: "\ x y :: real. x \ \ \ y \ \ \ x powr y \ \" sorry section \Exercise 3 -- 5 points\ text \Consider a variant of mergesort where the number of comparisons are counted.\ text \The aim is to prove that mergesort has a complexity of O(n log(n)). To this end, you will prove that on inputs of length $2^n$ there will be at most $2^n * n$ many comparisons.\ fun split_list :: "'a list \ 'a list \ 'a list" where "split_list (x # y # xs) = (case split_list xs of (one,two) \ (x # one, y # two))" | "split_list xs = (xs,[])" fun merge :: "'a :: linorder list \ 'a list \ 'a list \ nat" where "merge [] ys = (ys,0)" | "merge xs [] = (xs,0)" | "merge (x # xs) (y # ys) = (if x \ y then case merge xs (y # ys) of (zs,n) \ (x # zs, Suc n) else case merge (x # xs) ys of (zs,n) \ (y # zs, Suc n))" function (sequential) msort :: "'a :: linorder list \ 'a list \ nat" where "msort [] = ([], 0)" | "msort [x] = ([x], 0)" | "msort xs = (case split_list xs of (one,two) \ case msort one of (ys1,c1) \ case msort two of (ys2,c2) \ case merge ys1 ys2 of (ys,c3) \ (ys, c1 + c2 + c3))" by pat_completeness auto lemma split_len: "split_list xs = (one,two) \ length xs = length one + length two" by (induction xs arbitrary: one two rule: split_list.induct) (auto split: prod.splits) termination by (relation "measure length") (auto dest: split_len split: prod.splits) text \You will have to figure out useful properties of @{const split_list} and @{const merge} that help to prove the complexity of mergesort. Most of these are one-liners by using the right modifiers. Hints: - division on natural numbers is @{term "x div y"} and there also exists a predicate @{const even}. - besides @{thm list.splits}, @{thm nat.splits}, @{thm prod.splits}, etc., there also is a split-rule for if-then-else: @{thm if_split}\ text \For proving the complexity of mergesort (in combination with the other required property, I would be surprised to see a one-line solution, so you have to perform several manual steps.\ lemma msort: "msort xs = (ys, m) \ length xs = 2^n \ m \ n * 2^n \ length ys = length xs" proof (induction xs arbitrary: ys n m rule: msort.induct) case (3 x1 x2 xs ys n m) let ?xs = "x1 # x2 # xs" obtain one two where xs: "split_list ?xs = (one, two)" by force (* force splits pairs for you *) obtain ys1 c1 where one: "msort one = (ys1, c1)" by force show ?case sorry qed auto end