text\<open>Note that this definition of total validity \<open>\<Turnstile>\<^sub>t\<close> only
works if execution is deterministic (which it isin our case).\<close>
definition hoare_tvalid :: "assn \ com \ assn \ bool"
(\<open>\<Turnstile>\<^sub>t {(1_)}/ (_)/ {(1_)}\<close> 50) where "\\<^sub>t {P}c{Q} \ (\s. P s \ (\t. (c,s) \ t \ Q t))"
text\<open>Provability of Hoare triples in the proof system for total
correctness is written \<open>\<turnstile>\<^sub>t {P}c{Q}\<close> and defined
inductively. The rules for\<open>\<turnstile>\<^sub>t\<close> differ from those for \<open>\<turnstile>\<close> only in the one place where nontermination can arise: the \<^term>\<open>While\<close>-rule.\<close>
inductive
hoaret :: "assn \ com \ assn \ bool" (\\\<^sub>t ({(1_)}/ (_)/ {(1_)})\ 50) where
If: "\ \\<^sub>t {\s. P s \ bval b s} c\<^sub>1 {Q}; \\<^sub>t {\s. P s \ \ bval b s} c\<^sub>2 {Q} \ \<Longrightarrow> \<turnstile>\<^sub>t {P} IF b THEN c\<^sub>1 ELSE c\<^sub>2 {Q}" |
While: "(\n::nat. \<turnstile>\<^sub>t {\<lambda>s. P s \<and> bval b s \<and> T s n} c {\<lambda>s. P s \<and> (\<exists>n'<n. T s n')}) \<Longrightarrow> \<turnstile>\<^sub>t {\<lambda>s. P s \<and> (\<exists>n. T s n)} WHILE b DO c {\<lambda>s. P s \<and> \<not>bval b s}" |
conseq: "\ \s. P' s \ P s; \\<^sub>t {P}c{Q}; \s. Q s \ Q' s \ \ \<turnstile>\<^sub>t {P'}c{Q'}"
text\<open>The \<^term>\<open>While\<close>-rule is like the one for partial correctness but it
requires additionally that with every execution of the loop body some measure
relation @{term[source]"T :: state \ nat \ bool"} decreases.
The following functional version is more intuitive:\<close>
lemma While_fun: "\ \n::nat. \\<^sub>t {\s. P s \ bval b s \ n = f s} c {\s. P s \ f s < n}\ \<Longrightarrow> \<turnstile>\<^sub>t {P} WHILE b DO c {\<lambda>s. P s \<and> \<not>bval b s}" by (rule While [where T="\s n. n = f s", simplified])
text\<open>Building in the consequence rule:\<close>
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_fun': assumes"\n::nat. \\<^sub>t {\s. P s \ bval b s \ n = f s} 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_fun assms(2)])
text\<open>Our standard example:\<close>
lemma"\\<^sub>t {\s. s ''x'' = i} ''y'' ::= N 0;; wsum {\s. s ''y'' = sum i}" apply(rule Seq) prefer 2 apply(rule While_fun' [where P = "\s. (s ''y'' = sum i - sum(s ''x''))" and f = "\s. nat(s ''x'')"]) apply(rule Seq) prefer 2 apply(rule Assign) apply(rule Assign') apply simp apply(simp) apply(rule Assign') apply simp done
text\<open>Nested loops. This poses a problem for VCGs because the proof of the inner loop needs to
refer to outer loops. This works here because the invariant is not written down statically but
created in the context of a proof that has already introduced/fixed outer \<open>n\<close>s that can be
referred to.\<close>
lemma "\\<^sub>t {\_. True}
WHILE Less (N 0) (V ''x'')
DO (''x'' ::= Plus (V ''x'') (N(-1));; ''y'' ::= V ''x'';;
WHILE Less (N 0) (V ''y'') DO ''y'' ::= Plus (V ''y'') (N(-1)))
{\<lambda>_. True}" apply(rule While_fun'[where f = "\s. nat(s ''x'')"]) prefer 2 apply simp apply(rule_tac P\<^sub>2 = "\<lambda>s. nat(s ''x'') < n" in Seq) apply(rule_tac P\<^sub>2 = "\<lambda>s. nat(s ''x'') < n" in Seq) apply(rule Assign') apply simp apply(rule Assign') apply simp (* note that the invariant refers to the outer \<open>n\<close>: *) apply(rule While_fun'[where f = "\s. nat(s ''y'')"]) prefer 2 apply simp apply(rule Assign') apply simp done
text\<open>The soundness theorem:\<close>
theorem hoaret_sound: "\\<^sub>t {P}c{Q} \ \\<^sub>t {P}c{Q}" proof(unfold hoare_tvalid_def, induction rule: hoaret.induct) case (While P b T c) have"\ P s; T s n \ \ \t. (WHILE b DO c, s) \ t \ P t \ \ bval b t" for s n proof(induction"n" arbitrary: s rule: less_induct) case (less n) thus ?caseby (metis While.IH WhileFalse WhileTrue) qed thus ?caseby auto next caseIfthus ?caseby auto blast qed fastforce+
text\<open>
The completeness proof proceeds along the same lines as the one for partial
correctness. First we haveto strengthen our notion of weakest precondition to take termination into account:\<close>
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 (IF b THEN c\<^sub>1 ELSE c\<^sub>2) Q = (\s. wp\<^sub>t (if bval b s then c\<^sub>1 else c\<^sub>2) Q s)" apply(unfold wpt_def) apply(rule ext) apply auto done
text\<open>Now we define the number of iterations \<^term>\<open>WHILE b DO c\<close> needs to
terminate when started in state \<open>s\<close>. Because this is a truly partial function, we define it as an (inductive) relation first:\<close>
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\<open>The relation is in fact a function:\<close>
lemma Its_fun: "Its b c s n \ Its b c s n' \ n=n'" proof(induction arbitrary: n' rule:Its.induct) case Its_0 thus ?caseby(metis Its.cases) next case Its_Suc thus ?caseby(metis Its.cases big_step_determ) qed
text\<open>For all terminating loops, \<^const>\<open>Its\<close> yields a result:\<close>
lemma WHILE_Its: "(WHILE b DO c,s) \ t \ \n. Its b c s n" proof(induction"WHILE b DO c" s t rule: big_step_induct) case WhileFalse thus ?caseby (metis Its_0) next case WhileTrue thus ?caseby (metis Its_Suc) qed
lemma wpt_is_pre: "\\<^sub>t {wp\<^sub>t c Q} c {Q}" proof (induction c arbitrary: Q) case SKIP show ?caseby (auto intro:hoaret.Skip) next case Assign show ?caseby (auto intro:hoaret.Assign) next case Seq thus ?caseby (auto intro:hoaret.Seq) next caseIfthus ?caseby (auto intro:hoaret.If hoaret.conseq) next case (While b c) let ?w = "WHILE b DO c" let ?T = "Its b c" have 1: "\s. wp\<^sub>t ?w Q s \ wp\<^sub>t ?w Q s \ (\n. Its b c s n)" unfolding wpt_def by (metis WHILE_Its) let ?R = "\n s'. wp\<^sub>t ?w Q s' \ (\n' have"\s. wp\<^sub>t ?w Q s \ bval b s \ ?T s n \ wp\<^sub>t c (?R n) s" for n proof - have"wp\<^sub>t c (?R n) s" if "bval b s" and "?T s n" and "(?w, s) \ t" and "Q t" for s t proof - from\<open>bval b s\<close> and \<open>(?w, s) \<Rightarrow> t\<close> obtain s' where "(c,s) \ s'" "(?w,s') \ t" by auto from\<open>(?w, s') \<Rightarrow> t\<close> obtain n' where "?T s' n'" by (blast dest: WHILE_Its) with\<open>bval b s\<close> and \<open>(c, s) \<Rightarrow> s'\<close> have "?T s (Suc n')" by (rule Its_Suc) with\<open>?T s n\<close> have "n = Suc n'" by (rule Its_fun) with\<open>(c,s) \<Rightarrow> s'\<close> and \<open>(?w,s') \<Rightarrow> t\<close> and \<open>Q t\<close> and \<open>?T s' n'\<close> show ?thesis by (auto simp: wpt_def) qed thus ?thesis unfolding wpt_def by auto (* by (metis WhileE Its_Suc Its_fun WHILE_Its lessI) *) qed note 2 = hoaret.While[OF strengthen_pre[OF this While.IH]] have"\s. wp\<^sub>t ?w Q s \ \ bval b s \ Q s" by (auto simp add:wpt_def) with 1 2 show ?caseby (rule conseq) qed
text\<open>\noindent In the \<^term>\<open>While\<close>-case, \<^const>\<open>Its\<close> provides the obvious termination argument.
The actual completeness theorem follows directly, in the same manner
as for partial correctness:\<close>
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.