theory week08A_sol imports Main begin -- "Syntax and State Space" type_synonym vname = string type_synonym state = "vname \ nat" type_synonym aexp = "state \ nat" type_synonym bexp = "state \ bool" datatype com = SKIP | Assign vname aexp ("_ :== _ " [60,60] 60) | Semi com com ("_;; _" [50, 51] 50) | Cond bexp com com ("IF _ THEN _ ELSE _" [0,0,59] 60) | While bexp com ("WHILE _ DO _ OD" [0,45] 60) -- "Example Program" definition A :: vname where "A \ ''A''" definition B :: vname where "B \ ''B''" lemma [simp]: "A \ B" by (simp add: A_def B_def) lemma [simp]: "B \ A" by (simp add: A_def B_def) definition factorial :: com where "factorial \ B :== (\s. 1);; WHILE (\s. s A \ 0) DO B :== (\s. s B * s A);; A :== (\s. s A - 1) OD" -- "Execution" inductive eval :: "com \ state \ state \ bool" ("_/ \ _" [60,60] 61) where Skip [intro!,simp]: "(SKIP, s) \ s" | Assign [intro!,simp]: "(x :== a, s) \ s (x := a s)" | Semi [intro!]: "\ (c\<^isub>1,s) \ s''; (c\<^isub>2,s'') \ s' \ \ (c\<^isub>1;; c\<^isub>2, s) \ s'" | IfTrue: "\ b s; (c\<^isub>1,s) \ s' \ \ (IF b THEN c\<^isub>1 ELSE c\<^isub>2, s) \ s'" | IfFalse: "\ \b s; (c\<^isub>2,s) \ s' \ \ (IF b THEN c\<^isub>1 ELSE c\<^isub>2, s) \ s'" | WhileFalse: "\b s \ (WHILE b DO c OD, s) \ s" | WhileTrue: "\b s; (c,s) \ s''; (WHILE b DO c OD, s'') \ s'\ \ (WHILE b DO c OD, s) \ s'" lemmas eval_induct = eval.induct [split_format (complete)] thm eval_induct inductive_cases skip [elim!]: "(SKIP, s) \ s'" and assign [elim!]: "(x :== a, s) \ s'" and semi [elim!]: "(c\<^isub>1;; c\<^isub>2, s) \ s'" and "if" [elim!]: "(IF b THEN c\<^isub>1 ELSE c\<^isub>2, s) \ s'" and while: "(WHILE b DO c OD, s) \ s'" thm skip assign semi "if" while lemma skip_eq [simp]: "(SKIP, s) \ s' = (s' = s)" by blast lemma assign_eq [simp]: "(x :== a, s) \ s' = (s' = s (x := a s))" by blast -- --------------------------------------------------------------------- -- "Example Proof" primrec fac :: "nat \ nat" where "fac 0 = 1" |"fac (Suc n) = (Suc n) * fac n" lemma factorial': "(WHILE \s. 0 < s A DO B :== (\s. s B * s A) ;; A :== (\s. s A - Suc 0) OD, s(B := n)) \ s' \ s' B = n * fac (s A)" apply (induct "s A" arbitrary: s n) apply clarsimp apply (erule while) apply clarsimp apply simp apply (erule while) apply clarsimp apply clarsimp apply (drule_tac x="s (A := s A - Suc 0)" in meta_spec) apply clarsimp apply (drule sym) apply clarsimp apply (subgoal_tac "s(B := n + n * x, A := x) = s(A := x, B := n + n * x)") apply simp apply (simp add: add_mult_distrib2 add_mult_distrib) apply auto done lemma factorial_correct: "(factorial, s) \ s' \ s' B = fac (s A)" apply (unfold factorial_def) apply clarsimp apply (auto simp: factorial') done -- --------------------------------------------------------------------- type_synonym assn = "state => bool" definition hoare_valid :: "assn \ com \ assn \ bool" ("\ {(1_)}/ (_)/ {(1_)}" 50) where "\ {P} c {Q} \ \s s'. P s \ (c,s) \ s' \ Q s'" inductive hoare :: "assn \ com \ assn \ bool" ("\ ({(1_)}/ (_)/ {(1_)})" 50) where h_skip: "\ {P} SKIP {P}" | h_assign: "\ {\s. P (s(x:= a s))} x:==a {P}" | h_semi: "\ \ {P} c\<^isub>1 {R}; \ {R} c\<^isub>2 {Q} \ \ \ {P} c\<^isub>1;;c\<^isub>2 {Q}" | h_if: "\ \ {\s. P s \ b s} c\<^isub>1 {Q}; \ {\s. P s \ \b s} c\<^isub>2 {Q} \ \ \ {P} IF b THEN c\<^isub>1 ELSE c\<^isub>2 {Q}" | h_while: "\ \ {\s. P s \ b s} c {P}; \s. P s \ \b s \ Q s \ \ \ {P} WHILE b DO c OD {Q}" | conseq: "\ \s. P s \ P' s; \ {P'} c {Q'}; \s. Q' s \ Q s \ \ \ {P} c {Q}" -- "Soundness Proof" thm eval_induct lemma invariant': assumes inv: "\s s'. P s \ b s \ (c,s) \ s' \ P s'" shows "\ (w, s) \ s'; w = WHILE b DO c OD; P s \ \ P s' \ \b s'" apply (induct rule: eval_induct) apply simp_all apply clarsimp apply (insert inv) apply blast done lemma invariant: assumes inv: "\s. P s \ b s \ (\s'. (c,s) \ s' \ P s')" shows "\ (WHILE b DO c OD, s) \ s'; P s \ \ P s' \ \b s'" apply (rule invariant') apply (auto simp: inv) done theorem hoare_sound: assumes deriv: "\ {P} c {Q}" shows "\ {P} c {Q}" using deriv apply induct apply (simp add: hoare_valid_def) apply (simp add: hoare_valid_def) apply (simp add: hoare_valid_def) apply clarsimp apply blast apply (clarsimp simp: hoare_valid_def) apply blast apply (clarsimp simp: hoare_valid_def) apply (drule (2) invariant) apply clarsimp apply (clarsimp simp: hoare_valid_def) apply blast done -- -------------------------------------------------------------------------------------- -- "derived rules" lemma h_ass: "(\s. P s \ Q (s(x := a s))) \ \ {P} x :== a {Q}" apply (rule_tac Q'=Q in conseq) prefer 2 apply (rule h_assign) prefer 2 apply clarify apply blast done -- "example proof" lemma "\ {\s. True} x :== (\s. 2) {\s. s x = 2}" apply (rule h_ass) apply simp done lemma "\ {\s. s A = n} factorial {\s. s B = fac n}" apply (unfold factorial_def) apply (rule h_semi) prefer 2 apply (rule_tac P="\s. s B * fac (s A) = fac n" in h_while) apply (rule h_semi) prefer 2 apply (rule h_assign) apply (rule h_ass) apply clarsimp apply (case_tac "s A") apply simp apply simp apply (simp add: add_mult_distrib2 add_mult_distrib) apply clarsimp apply (rule h_ass) apply clarsimp done end