header{* Hoare Logic for Total Correctness *} theory HoareT imports Hoare_Sound_Complete begin text{* Now that we have termination, we can define total validity, @{text"\\<^sub>t"}, as partial validity and guaranteed termination:*} definition hoare_tvalid :: "assn \ com \ assn \ bool" ("\\<^sub>t {(1_)}/ (_)/ {(1_)}" 50) where "\\<^sub>t {P}c{Q} \ \s. P s \ (\t. (c,s) \ t \ Q t)" text{* Proveability of Hoare triples in the proof system for total correctness is written @{text"\\<^sub>t {P}c{Q}"} and defined inductively. The rules for @{text"\\<^sub>t"} differ from those for @{text"\"} only in the one place where nontermination can arise: the @{term While}-rule. *} inductive hoaret :: "assn \ com \ assn \ bool" ("\\<^sub>t ({(1_)}/ (_)/ {(1_)})" 50) where Skip: "\\<^sub>t {P} SKIP {P}" | Assign: "\\<^sub>t {\s. P(s[a/x])} x::=a {P}" | Semi: "\ \\<^sub>t {P\<^isub>1} c\<^isub>1 {P\<^isub>2}; \\<^sub>t {P\<^isub>2} c\<^isub>2 {P\<^isub>3} \ \ \\<^sub>t {P\<^isub>1} c\<^isub>1;c\<^isub>2 {P\<^isub>3}" | If: "\ \\<^sub>t {\s. P s \ bval b s} c\<^isub>1 {Q}; \\<^sub>t {\s. P s \ \ bval b s} c\<^isub>2 {Q} \ \ \\<^sub>t {P} IF b THEN c\<^isub>1 ELSE c\<^isub>2 {Q}" | While: "\ \n::nat. \\<^sub>t {\s. P s \ bval b s \ f s = n} c {\s. P s \ f s < n}\ \ \\<^sub>t {P} WHILE b DO c {\s. P s \ \bval b s}" | conseq: "\ \s. P' s \ P s; \\<^sub>t {P}c{Q}; \s. Q s \ Q' s \ \ \\<^sub>t {P'}c{Q'}" text{* The @{term While}-rule is like the one for partial correctness but it requires additionally that with every execution of the loop body some measure function @{term[source]"f :: state \ nat"} decreases. *} lemma strengthen_pre: "\ \s. P' s \ P s; \\<^sub>t {P} c {Q} \ \ \\<^sub>t {P'} c {Q}" by (metis conseq) lemma weaken_post: "\ \\<^sub>t {P} c {Q}; \s. Q s \ Q' s \ \ \\<^sub>t {P} c {Q'}" by (metis conseq) lemma Assign': "\s. P s \ Q(s[a/x]) \ \\<^sub>t {P} x ::= a {Q}" by (simp add: strengthen_pre[OF _ Assign]) lemma While': assumes "\n::nat. \\<^sub>t {\s. P s \ bval b s \ f s = n} c {\s. P s \ f s < n}" and "\s. P s \ \ bval b s \ Q s" shows "\\<^sub>t {P} WHILE b DO c {Q}" by(blast intro: assms(1) weaken_post[OF While assms(2)]) text{* Our standard example: *} abbreviation "w n == WHILE Less (V 1) (N n) DO ( 1 ::= Plus (V 1) (N 1); 0 ::= Plus (V 0) (V 1) )" lemma "\\<^sub>t {\s. True} 0 ::= N 0; 1 ::= N 0; w n {\s. s 0 = \ {1 .. n}}" apply(rule Semi) prefer 2 apply(rule While' [where P = "\s. s 0 = \ {1..s 1} \ s 1 \ n" and f = "\s. n - s 1"]) apply(rule Semi) prefer 2 apply(rule Assign) apply(rule Assign') apply simp apply arith apply fastsimp apply(rule Semi) prefer 2 apply(rule Assign) apply(rule Assign') apply simp done text{* The soundness theorem: *} theorem hoaret_sound: "\\<^sub>t {P}c{Q} \ \\<^sub>t {P}c{Q}" proof(unfold hoare_tvalid_def, induct rule: hoaret.induct) case (While P b f c) show ?case proof fix s show "P s \ (\t. (WHILE b DO c, s) \ t \ P t \ \ bval b t)" proof(induct "f s" arbitrary: s rule: less_induct) case (less n) thus ?case by (metis While(2) WhileFalse WhileTrue) qed qed next case If thus ?case by auto blast qed fastsimp+ text{* The completeness proof proceeds along the same lines as the one for partial correctness. First we have to strengthen our notion of weakest precondition to take termination into account: *} definition wpt :: "com \ assn \ assn" ("wp\<^sub>t") where "wp\<^sub>t c Q \ \s. \t. (c,s) \ t \ Q t" lemma [simp]: "wp\<^sub>t SKIP Q = Q"; by(auto intro!: ext simp: wpt_def) lemma [simp]: "wp\<^sub>t (x ::= e) Q = (\s. Q(s(x := aval e s)))" by(auto intro!: ext simp: wpt_def) lemma [simp]: "wp\<^sub>t (c\<^isub>1;c\<^isub>2) Q = wp\<^sub>t c\<^isub>1 (wp\<^sub>t c\<^isub>2 Q)"; unfolding wpt_def apply(rule ext) apply auto done lemma [simp]: "wp\<^sub>t (IF b THEN c\<^isub>1 ELSE c\<^isub>2) Q = (\s. wp\<^sub>t (if bval b s then c\<^isub>1 else c\<^isub>2) Q s)"; apply(unfold wpt_def) apply(rule ext) apply auto done text{* Now we define the number of iterations @{term "WHILE b DO c"} needs to terminate when started in state @{text s}. Because this is a truly partial function, we define it as an (inductive) relation first: *} inductive Its :: "bexp \ com \ state \ nat \ bool" where Its_0: "\ bval b s \ Its b c s 0" | Its_Suc: "\ bval b s; (c,s) \ s'; Its b c s' n \ \ Its b c s (Suc n)" text{* The relation is in fact a function: *} lemma Its_fun: "Its b c s n \ Its b c s n' \ n=n'" proof(induct arbitrary: n' rule:Its.induct) (* new release: case Its_0 thus ?case by(metis Its.cases) next case Its_Suc thus ?case by(metis Its.cases big_step_determ) qed *) case Its_0 from this(1) Its.cases[OF this(2)] show ?case by metis next case (Its_Suc b s c s' n n') note C = this from this(5) show ?case proof cases case Its_0 with Its_Suc(1) show ?thesis by blast next case Its_Suc with C show ?thesis by(metis big_step_determ) qed qed text{* For all terminating loops, @{const Its} yields a result: *} lemma WHILE_Its: "(WHILE b DO c,s) \ t \ \n. Its b c s n" proof(induct "WHILE b DO c" s t rule: big_step_induct) case WhileFalse thus ?case by (metis Its_0) next case WhileTrue thus ?case by (metis Its_Suc) qed text{* Now the relation is turned into a function with the help of the description operator @{text THE}: *} definition its :: "bexp \ com \ state \ nat" where "its b c s = (THE n. Its b c s n)" text{* The key property: every loop iteration increases @{const its} by 1. *} lemma its_Suc: "\ bval b s; (c, s) \ s'; (WHILE b DO c, s') \ t\ \ its b c s = Suc(its b c s')" by (metis its_def WHILE_Its Its.intros(2) Its_fun the_equality) lemma wpt_is_pre: "\\<^sub>t {wp\<^sub>t c Q} c {Q}" proof (induct c arbitrary: Q) case SKIP show ?case by simp (blast intro:hoaret.Skip) next case Assign show ?case by simp (blast intro:hoaret.Assign) next case Semi thus ?case by simp (blast intro:hoaret.Semi) next case If thus ?case by simp (blast intro:hoaret.If hoaret.conseq) next case (While b c) let ?w = "WHILE b DO c" { fix n have "\s. wp\<^sub>t ?w Q s \ bval b s \ its b c s = n \ wp\<^sub>t c (\s'. wp\<^sub>t ?w Q s' \ its b c s' < n) s" unfolding wpt_def by (metis WhileE its_Suc lessI) note strengthen_pre[OF this While] } note hoaret.While[OF this] moreover have "\s. wp\<^sub>t ?w Q s \ \ bval b s \ Q s" by (auto simp add:wpt_def) ultimately show ?case by(rule weaken_post) qed text{*\noindent In the @{term While}-case, @{const its} provides the obvious termination argument. The actual completeness theorem follows directly, in the same manner as for partial correctness: *} theorem hoaret_complete: "\\<^sub>t {P}c{Q} \ \\<^sub>t {P}c{Q}" apply(rule strengthen_pre[OF _ wpt_is_pre]) apply(auto simp: hoare_tvalid_def hoare_valid_def wpt_def) done end