theory week09B_demo_gcd_sol imports WhileLoopRule "HOL-Eisbach.Eisbach" begin definition gcd' :: "nat \ nat \ ('s,nat) nondet_monad" where "gcd' a b \ do { (a, b) \ whileLoop (\(a, b) b. 0 < a) (\(a, b). return (b mod a, a)) (a, b); return b }" lemma prod_case_wp: assumes "\P\ f (fst x) (snd x) \Q\" shows "\P\ case x of (a,b) \ f a b \Q\" using assms apply(auto simp: valid_def split: prod.splits) done lemma gcd'_correct: "\\_. True\ gcd' x y \\r s. r = gcd x y\" unfolding gcd'_def apply (rule bind_wp) apply (rule prod_case_wp) apply (rule return_wp) apply (rule hoare_weaken_pre) apply (rule_tac I="\(a,b) s. gcd x y = gcd a b" in whileLoop_wp) apply (rule prod_case_wp) apply (rule hoare_weaken_pre, rule return_wp) apply clarsimp find_theorems gcd "_ mod _" find_theorems "gcd ?a ?b = gcd ?b ?a" apply (simp add: gcd.commute flip: gcd_red_nat) apply clarsimp apply clarsimp done (* Same, but more automated: AutoCorres provides a similar proof method "wp" that you are allowed to use in assignment 3. *) lemmas wp_thms = bind_wp return_wp prod_case_wp method wp = (rule hoare_weaken_pre, (rule wp_thms)+)[1] lemma gcd'_correct2: "\\_. True\ gcd' x y \\r s. r = gcd x y\" unfolding gcd'_def apply wp apply (rule whileLoop_wp[where I="\(a,b) s. gcd x y = gcd a b"]) apply wp apply clarsimp apply (metis gcd.commute gcd_red_nat) apply clarsimp apply clarsimp done end