Our site saves small pieces of text information (cookies) on your device in order to deliver better content and for statistical purposes. You can disable the usage of cookies by changing the settings of your browser. By browsing our website without changing the browser settings you grant us permission to store that information on your device.

Homework 10

This is the task corresponding to homework 10.

Resources

Definitions File

```theory Defs
imports Main
begin

type_synonym vname = string
type_synonym val = int
type_synonym state = "vname \<Rightarrow> val"

datatype aexp
= N int | V vname | Plus aexp aexp
| Minus aexp aexp | Mul aexp aexp | Div aexp aexp

fun aval :: "aexp \<Rightarrow> state \<Rightarrow> val" where
"aval (N n) s = n" |
"aval (V x) s = s x" |
"aval (Plus a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s + aval a\<^sub>2 s" |
"aval (Div a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s div aval a\<^sub>2 s" |
"aval (Mul a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s * aval a\<^sub>2 s" |
"aval (Minus a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s - aval a\<^sub>2 s"

definition null_state ("<>") where
"null_state \<equiv> \<lambda>x. 0"
syntax
"_State" :: "updbinds => 'a" ("<_>")
translations
"_State ms" == "_Update <> ms"
"_State (_updbinds b bs)" <= "_Update (_State b) bs"

datatype bexp = Bc bool | Not bexp | And bexp bexp | Less aexp aexp

fun bval :: "bexp \<Rightarrow> state \<Rightarrow> bool" where
"bval (Bc v) s = v" |
"bval (Not b) s = (\<not> bval b s)" |
"bval (And b\<^sub>1 b\<^sub>2) s = (bval b\<^sub>1 s \<and> bval b\<^sub>2 s)" |
"bval (Less a\<^sub>1 a\<^sub>2) s = (aval a\<^sub>1 s < aval a\<^sub>2 s)"

datatype
com = SKIP
| Assign vname aexp       ("_ ::= _" [1000, 61] 61)
| Seq    com  com         ("_;;/ _"  [60, 61] 60)
| If     bexp com com     ("(IF _/ THEN _/ ELSE _)"  [0, 0, 61] 61)
| While  bexp com         ("(WHILE _/ DO _)"  [0, 61] 61)

inductive
big_step :: "com \<times> state \<Rightarrow> state \<Rightarrow> bool" (infix "\<Rightarrow>" 55)
where
Skip: "(SKIP,s) \<Rightarrow> s" |
Assign: "(x ::= a,s) \<Rightarrow> s(x := aval a s)" |
Seq: "\<lbrakk> (c\<^sub>1,s\<^sub>1) \<Rightarrow> s\<^sub>2;  (c\<^sub>2,s\<^sub>2) \<Rightarrow> s\<^sub>3 \<rbrakk> \<Longrightarrow> (c\<^sub>1;;c\<^sub>2, s\<^sub>1) \<Rightarrow> s\<^sub>3" |
IfTrue: "\<lbrakk> bval b s;  (c\<^sub>1,s) \<Rightarrow> t \<rbrakk> \<Longrightarrow> (IF b THEN c\<^sub>1 ELSE c\<^sub>2, s) \<Rightarrow> t" |
IfFalse: "\<lbrakk> \<not>bval b s;  (c\<^sub>2,s) \<Rightarrow> t \<rbrakk> \<Longrightarrow> (IF b THEN c\<^sub>1 ELSE c\<^sub>2, s) \<Rightarrow> t" |
WhileFalse: "\<not>bval b s \<Longrightarrow> (WHILE b DO c,s) \<Rightarrow> s" |
WhileTrue:
"\<lbrakk> bval b s\<^sub>1;  (c,s\<^sub>1) \<Rightarrow> s\<^sub>2;  (WHILE b DO c, s\<^sub>2) \<Rightarrow> s\<^sub>3 \<rbrakk>
\<Longrightarrow> (WHILE b DO c, s\<^sub>1) \<Rightarrow> s\<^sub>3"

code_pred big_step .

declare big_step.intros [intro]
lemmas big_step_induct = big_step.induct[split_format(complete)]
thm big_step_induct

inductive_cases SkipE[elim!]: "(SKIP,s) \<Rightarrow> t"
thm SkipE
inductive_cases AssignE[elim!]: "(x ::= a,s) \<Rightarrow> t"
thm AssignE
inductive_cases SeqE[elim!]: "(c1;;c2,s1) \<Rightarrow> s3"
thm SeqE
inductive_cases IfE[elim!]: "(IF b THEN c1 ELSE c2,s) \<Rightarrow> t"
thm IfE

inductive_cases WhileE[elim]: "(WHILE b DO c,s) \<Rightarrow> t"
thm WhileE

theorem big_step_determ: "\<lbrakk> (c,s) \<Rightarrow> t; (c,s) \<Rightarrow> u \<rbrakk> \<Longrightarrow> u = t"
by (induction arbitrary: u rule: big_step.induct) blast+

abbreviation
equiv_c :: "com \<Rightarrow> com \<Rightarrow> bool" (infix "\<sim>" 50) where
"c \<sim> c' \<equiv> (\<forall>s t. (c,s) \<Rightarrow> t  =  (c',s) \<Rightarrow> t)"

lemma unfold_while:
"(WHILE b DO c) \<sim> (IF b THEN c;; WHILE b DO c ELSE SKIP)" (is "?w \<sim> ?iw")
proof -
have "(?iw, s) \<Rightarrow> t" if assm: "(?w, s) \<Rightarrow> t" for s t
proof -
from assm show ?thesis
proof cases
case WhileFalse
thus ?thesis by blast
next
case WhileTrue
from \<open>bval b s\<close> \<open>(?w, s) \<Rightarrow> t\<close> obtain s' where
"(c, s) \<Rightarrow> s'" and "(?w, s') \<Rightarrow> t" by auto
hence "(c;; ?w, s) \<Rightarrow> t" by (rule Seq)
with \<open>bval b s\<close> show ?thesis by (rule IfTrue)
qed
qed
moreover
have "(?w, s) \<Rightarrow> t" if assm: "(?iw, s) \<Rightarrow> t" for s t
proof -
from assm show ?thesis
proof cases
case IfFalse
hence "s = t" using \<open>(?iw, s) \<Rightarrow> t\<close> by blast
thus ?thesis using \<open>\<not>bval b s\<close> by blast
next
case IfTrue
from \<open>(c;; ?w, s) \<Rightarrow> t\<close> obtain s' where
"(c, s) \<Rightarrow> s'" and "(?w, s') \<Rightarrow> t" by auto
with \<open>bval b s\<close> show ?thesis by (rule WhileTrue)
qed
qed
ultimately
show ?thesis by blast
qed

paragraph "Hoare"

type_synonym assn = "state \<Rightarrow> bool"

abbreviation state_subst :: "state \<Rightarrow> aexp \<Rightarrow> vname \<Rightarrow> state"
("_[_'/_]" [1000,0,0] 999)
where "s[a/x] == s(x := aval a s)"

paragraph "Partial correctness"

definition
partial_hoare_valid :: "assn \<Rightarrow> com \<Rightarrow> assn \<Rightarrow> bool" ("\<Turnstile> {(1_)}/ (_)/ {(1_)}" 50) where
"\<Turnstile> {P}c{Q} = (\<forall>s t. P s \<and> (c,s) \<Rightarrow> t  \<longrightarrow>  Q t)"

inductive
partial_hoare :: "assn \<Rightarrow> com \<Rightarrow> assn \<Rightarrow> bool" ("\<turnstile> ({(1_)}/ (_)/ {(1_)})" 50)
where
partial_Skip: "\<turnstile> {P} SKIP {P}"  |

partial_Assign:  "\<turnstile> {\<lambda>s. P(s[a/x])} x::=a {P}"  |

partial_Seq: "\<lbrakk> \<turnstile> {P} c\<^sub>1 {Q};  \<turnstile> {Q} c\<^sub>2 {R} \<rbrakk>
\<Longrightarrow> \<turnstile> {P} c\<^sub>1;;c\<^sub>2 {R}"  |

partial_If: "\<lbrakk> \<turnstile> {\<lambda>s. P s \<and> bval b s} c\<^sub>1 {Q};  \<turnstile> {\<lambda>s. P s \<and> \<not> bval b s} c\<^sub>2 {Q} \<rbrakk>
\<Longrightarrow> \<turnstile> {P} IF b THEN c\<^sub>1 ELSE c\<^sub>2 {Q}"  |

partial_While: "\<turnstile> {\<lambda>s. P s \<and> bval b s} c {P} \<Longrightarrow>
\<turnstile> {P} WHILE b DO c {\<lambda>s. P s \<and> \<not> bval b s}"  |

partial_conseq: "\<lbrakk> \<forall>s. P' s \<longrightarrow> P s;  \<turnstile> {P} c {Q};  \<forall>s. Q s \<longrightarrow> Q' s \<rbrakk>
\<Longrightarrow> \<turnstile> {P'} c {Q'}"

lemmas [simp] = partial_hoare.partial_Skip partial_hoare.partial_Assign partial_hoare.partial_Seq partial_If

lemmas [intro!] = partial_hoare.partial_Skip partial_hoare.partial_Assign partial_hoare.partial_Seq partial_hoare.partial_If

lemma partial_strengthen_pre:
"\<lbrakk> \<forall>s. P' s \<longrightarrow> P s;  \<turnstile> {P} c {Q} \<rbrakk> \<Longrightarrow> \<turnstile> {P'} c {Q}"
by (blast intro: partial_conseq)

lemma partial_weaken_post:
"\<lbrakk> \<turnstile> {P} c {Q};  \<forall>s. Q s \<longrightarrow> Q' s \<rbrakk> \<Longrightarrow>  \<turnstile> {P} c {Q'}"
by (blast intro: partial_conseq)

lemma partial_Assign': "\<forall>s. P s \<longrightarrow> Q(s[a/x]) \<Longrightarrow> \<turnstile> {P} x ::= a {Q}"
by (simp add: partial_strengthen_pre[OF _ partial_Assign])

lemma partial_While':
assumes "\<turnstile> {\<lambda>s. P s \<and> bval b s} c {P}" and "\<forall>s. P s \<and> \<not> bval b s \<longrightarrow> Q s"
shows "\<turnstile> {P} WHILE b DO c {Q}"
by(rule partial_weaken_post[OF partial_While[OF assms(1)] assms(2)])

definition partial_wp :: "com \<Rightarrow> assn \<Rightarrow> assn" where
"partial_wp c Q = (\<lambda>s. \<forall>t. (c,s) \<Rightarrow> t  \<longrightarrow>  Q t)"

lemma partial_wp_SKIP[simp]: "partial_wp SKIP Q = Q"
by (rule ext) (auto simp: partial_wp_def)

lemma partial_wp_Ass[simp]: "partial_wp (x::=a) Q = (\<lambda>s. Q(s[a/x]))"
by (rule ext) (auto simp: partial_wp_def)

lemma partial_wp_partial_Seq[simp]: "partial_wp (c\<^sub>1;;c\<^sub>2) Q = partial_wp c\<^sub>1 (partial_wp c\<^sub>2 Q)"
by (rule ext) (auto simp: partial_wp_def)

lemma partial_wp_partial_If[simp]:
"partial_wp (IF b THEN c\<^sub>1 ELSE c\<^sub>2) Q =
(\<lambda>s. if bval b s then partial_wp c\<^sub>1 Q s else partial_wp c\<^sub>2 Q s)"
by (rule ext) (auto simp: partial_wp_def)

lemma partial_wp_partial_While_partial_If:
"partial_wp (WHILE b DO c) Q s =
partial_wp (IF b THEN c;;WHILE b DO c ELSE SKIP) Q s"
unfolding partial_wp_def by (metis unfold_while)

lemma partial_wp_partial_While_True[simp]: "bval b s \<Longrightarrow>
partial_wp (WHILE b DO c) Q s = partial_wp (c;; WHILE b DO c) Q s"

lemma partial_wp_partial_While_False[simp]: "\<not> bval b s \<Longrightarrow> partial_wp (WHILE b DO c) Q s = Q s"

lemma partial_wp_is_pre: "\<turnstile> {partial_wp c Q} c {Q}"
proof(induction c arbitrary: Q)
case If thus ?case by(auto intro: partial_hoare.partial_conseq)
next
case (While b c)
let ?w = "WHILE b DO c"
show "\<turnstile> {partial_wp ?w Q} ?w {Q}"
proof(rule partial_While')
show "\<turnstile> {\<lambda>s. partial_wp ?w Q s \<and> bval b s} c {partial_wp ?w Q}"
proof(rule partial_strengthen_pre[OF _ While.IH])
show "\<forall>s. partial_wp ?w Q s \<and> bval b s \<longrightarrow> partial_wp c (partial_wp ?w Q) s" by auto
qed
show "\<forall>s. partial_wp ?w Q s \<and> \<not> bval b s \<longrightarrow> Q s" by auto
qed
qed auto

lemma partial_hoare_complete: assumes "\<Turnstile> {P}c{Q}" shows "\<turnstile> {P}c{Q}"
proof(rule partial_strengthen_pre)
show "\<forall>s. P s \<longrightarrow> partial_wp c Q s" using assms
by (auto simp: partial_hoare_valid_def partial_wp_def)
show "\<turnstile> {partial_wp c Q} c {Q}" by(rule partial_wp_is_pre)
qed

paragraph "Annotated commands"

datatype acom =
Aassign vname aexp     ("(_ ::= _)" [1000, 61] 61) |
Aseq   acom acom       ("_;;/ _"  [60, 61] 60) |
Aif bexp acom acom     ("(IF _/ THEN _/ ELSE _)"  [0, 0, 61] 61) |
Awhile "state \<Rightarrow> nat" assn bexp acom
("({_,_}/ WHILE _/ DO _)"  [0, 0, 61] 61)

bundle ACOM begin
no_notation SKIP ("SKIP")
no_notation Assign ("_ ::= _" [1000, 61] 61)
no_notation Seq    ("_;;/ _"  [60, 61] 60)
no_notation If ("(IF _/ THEN _/ ELSE _)"  [0, 0, 61] 61)
notation Aassign ("(_ ::= _)" [1000, 61] 61)
notation Aseq ("_;;/ _"  [60, 61] 60)
notation Aif ("(IF _/ THEN _/ ELSE _)"  [0, 0, 61] 61)
end

bundle COM begin
no_notation Aassign ("(_ ::= _)" [1000, 61] 61)
no_notation Aseq ("_;;/ _"  [60, 61] 60)
no_notation Aif ("(IF _/ THEN _/ ELSE _)"  [0, 0, 61] 61)
notation SKIP ("SKIP")
notation Assign ("_ ::= _" [1000, 61] 61)
notation Seq    ("_;;/ _"  [60, 61] 60)
notation If ("(IF _/ THEN _/ ELSE _)"  [0, 0, 61] 61)
end

unbundle ACOM

fun strip :: "acom \<Rightarrow> com" where
"strip SKIP = com.SKIP" |
"strip (x ::= a) = com.Assign x a" |
"strip (C\<^sub>1;; C\<^sub>2) = com.Seq (strip C\<^sub>1) (strip C\<^sub>2)" |
"strip (IF b THEN C\<^sub>1 ELSE C\<^sub>2) = com.If b (strip C\<^sub>1) (strip C\<^sub>2)" |
"strip ({_,_} WHILE b DO C) = com.While b (strip C)"

paragraph "VCG for partial correctness"

fun partial_pre :: "acom \<Rightarrow> assn \<Rightarrow> assn" where
"partial_pre SKIP Q = Q" |
"partial_pre (x ::= a) Q = (\<lambda>s. Q(s(x := aval a s)))" |
"partial_pre (C\<^sub>1;; C\<^sub>2) Q = partial_pre C\<^sub>1 (partial_pre C\<^sub>2 Q)" |
"partial_pre (IF b THEN C\<^sub>1 ELSE C\<^sub>2) Q =
(\<lambda>s. if bval b s then partial_pre C\<^sub>1 Q s else partial_pre C\<^sub>2 Q s)" |
"partial_pre ({_,I} WHILE b DO C) Q = I"

fun partial_vc :: "acom \<Rightarrow> assn \<Rightarrow> bool" where
"partial_vc SKIP Q = True" |
"partial_vc (x ::= a) Q = True" |
"partial_vc (C\<^sub>1;; C\<^sub>2) Q = (partial_vc C\<^sub>1 (partial_pre C\<^sub>2 Q) \<and> partial_vc C\<^sub>2 Q)" |
"partial_vc (IF b THEN C\<^sub>1 ELSE C\<^sub>2) Q = (partial_vc C\<^sub>1 Q \<and> partial_vc C\<^sub>2 Q)" |
"partial_vc ({_,I} WHILE b DO C) Q =
((\<forall>s. (I s \<and> bval b s \<longrightarrow> partial_pre C I s) \<and>
(I s \<and> \<not> bval b s \<longrightarrow> Q s)) \<and>
partial_vc C I)"

lemma partial_vc_sound: "partial_vc C Q \<Longrightarrow> \<turnstile> {partial_pre C Q} strip C {Q}"
proof(induction C arbitrary: Q)
case (Awhile _ I b C)
show ?case
proof(simp, rule partial_While')
from \<open>partial_vc (Awhile _ I b C) Q\<close>
have partial_vc: "partial_vc C I" and IQ: "\<forall>s. I s \<and> \<not> bval b s \<longrightarrow> Q s" and
partial_pre: "\<forall>s. I s \<and> bval b s \<longrightarrow> partial_pre C I s" by simp_all
have "\<turnstile> {partial_pre C I} strip C {I}" by(rule Awhile.IH[OF partial_vc])
with partial_pre show "\<turnstile> {\<lambda>s. I s \<and> bval b s} strip C {I}"
by(rule partial_strengthen_pre)
show "\<forall>s. I s \<and> \<not>bval b s \<longrightarrow> Q s" by(rule IQ)
qed
qed (auto intro: partial_conseq)

corollary partial_vc_sound':
"\<lbrakk> partial_vc C Q; \<forall>s. P s \<longrightarrow> partial_pre C Q s \<rbrakk> \<Longrightarrow> \<turnstile> {P} strip C {Q}"
by (metis partial_strengthen_pre partial_vc_sound)

unbundle COM

paragraph "Total correctness"

definition hoare_tvalid :: "assn \<Rightarrow> com \<Rightarrow> assn \<Rightarrow> bool"
("\<Turnstile>\<^sub>t {(1_)}/ (_)/ {(1_)}" 50) where
"\<Turnstile>\<^sub>t {P}c{Q}  \<longleftrightarrow>  (\<forall>s. P s \<longrightarrow> (\<exists>t. (c,s) \<Rightarrow> t \<and> Q t))"

inductive
hoaret :: "assn \<Rightarrow> com \<Rightarrow> assn \<Rightarrow> bool" ("\<turnstile>\<^sub>t ({(1_)}/ (_)/ {(1_)})" 50)
where
Skip:  "\<turnstile>\<^sub>t {P} SKIP {P}"  |

Assign:  "\<turnstile>\<^sub>t {\<lambda>s. P(s[a/x])} x::=a {P}"  |

Seq: "\<lbrakk> \<turnstile>\<^sub>t {P\<^sub>1} c\<^sub>1 {P\<^sub>2}; \<turnstile>\<^sub>t {P\<^sub>2} c\<^sub>2 {P\<^sub>3} \<rbrakk> \<Longrightarrow> \<turnstile>\<^sub>t {P\<^sub>1} c\<^sub>1;;c\<^sub>2 {P\<^sub>3}"  |

If: "\<lbrakk> \<turnstile>\<^sub>t {\<lambda>s. P s \<and> bval b s} c\<^sub>1 {Q}; \<turnstile>\<^sub>t {\<lambda>s. P s \<and> \<not> bval b s} c\<^sub>2 {Q} \<rbrakk>
\<Longrightarrow> \<turnstile>\<^sub>t {P} IF b THEN c\<^sub>1 ELSE c\<^sub>2 {Q}"  |

While:
"(\<And>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: "\<lbrakk> \<forall>s. P' s \<longrightarrow> P s; \<turnstile>\<^sub>t {P}c{Q}; \<forall>s. Q s \<longrightarrow> Q' s  \<rbrakk> \<Longrightarrow>
\<turnstile>\<^sub>t {P'}c{Q'}"

lemma While_fun:
"\<lbrakk> \<And>n::nat. \<turnstile>\<^sub>t {\<lambda>s. P s \<and> bval b s \<and> n = f s} c {\<lambda>s. P s \<and> f s < n}\<rbrakk>
\<Longrightarrow> \<turnstile>\<^sub>t {P} WHILE b DO c {\<lambda>s. P s \<and> \<not>bval b s}"
by (rule While [where T="\<lambda>s n. n = f s", simplified])

lemma strengthen_pre:
"\<lbrakk> \<forall>s. P' s \<longrightarrow> P s;  \<turnstile>\<^sub>t {P} c {Q} \<rbrakk> \<Longrightarrow> \<turnstile>\<^sub>t {P'} c {Q}"
by (metis conseq)

lemma weaken_post:
"\<lbrakk> \<turnstile>\<^sub>t {P} c {Q};  \<forall>s. Q s \<longrightarrow> Q' s \<rbrakk> \<Longrightarrow>  \<turnstile>\<^sub>t {P} c {Q'}"
by (metis conseq)

lemma Assign': "\<forall>s. P s \<longrightarrow> Q(s[a/x]) \<Longrightarrow> \<turnstile>\<^sub>t {P} x ::= a {Q}"
by (simp add: strengthen_pre[OF _ Assign])

lemma While_fun':
assumes "\<And>n::nat. \<turnstile>\<^sub>t {\<lambda>s. P s \<and> bval b s \<and> n = f s} c {\<lambda>s. P s \<and> f s < n}"
and "\<forall>s. P s \<and> \<not> bval b s \<longrightarrow> Q s"
shows "\<turnstile>\<^sub>t {P} WHILE b DO c {Q}"
by(blast intro: assms(1) weaken_post[OF While_fun assms(2)])

theorem hoaret_sound: "\<turnstile>\<^sub>t {P}c{Q}  \<Longrightarrow>  \<Turnstile>\<^sub>t {P}c{Q}"
proof(unfold hoare_tvalid_def, induction rule: hoaret.induct)
case (While P b T c)
have "\<lbrakk> P s; T s n \<rbrakk> \<Longrightarrow> \<exists>t. (WHILE b DO c, s) \<Rightarrow> t \<and> P t \<and> \<not> bval b t" for s n
proof(induction "n" arbitrary: s rule: less_induct)
case (less n) thus ?case by (metis While.IH WhileFalse WhileTrue)
qed
thus ?case by auto
next
case If thus ?case by auto blast
qed fastforce+

definition wpt :: "com \<Rightarrow> assn \<Rightarrow> assn" ("wp\<^sub>t") where
"wp\<^sub>t c Q  =  (\<lambda>s. \<exists>t. (c,s) \<Rightarrow> t \<and> 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 = (\<lambda>s. Q(s(x := aval e s)))"
by(auto intro!: ext simp: wpt_def)

lemma [simp]: "wp\<^sub>t (c\<^sub>1;;c\<^sub>2) Q = wp\<^sub>t c\<^sub>1 (wp\<^sub>t c\<^sub>2 Q)"
unfolding wpt_def
apply(rule ext)
apply auto
done

lemma [simp]:
"wp\<^sub>t (IF b THEN c\<^sub>1 ELSE c\<^sub>2) Q = (\<lambda>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

inductive Its :: "bexp \<Rightarrow> com \<Rightarrow> state \<Rightarrow> nat \<Rightarrow> bool" where
Its_0: "\<not> bval b s \<Longrightarrow> Its b c s 0" |
Its_Suc: "\<lbrakk> bval b s;  (c,s) \<Rightarrow> s';  Its b c s' n \<rbrakk> \<Longrightarrow> Its b c s (Suc n)"

lemma Its_fun: "Its b c s n \<Longrightarrow> Its b c s n' \<Longrightarrow> n=n'"
proof(induction arbitrary: n' rule:Its.induct)
case Its_0 thus ?case by(metis Its.cases)
next
case Its_Suc thus ?case by(metis Its.cases big_step_determ)
qed

lemma WHILE_Its: "(WHILE b DO c,s) \<Rightarrow> t \<Longrightarrow> \<exists>n. Its b c s n"
proof(induction "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

lemma wpt_is_pre: "\<turnstile>\<^sub>t {wp\<^sub>t c Q} c {Q}"
proof (induction c arbitrary: Q)
case SKIP show ?case by (auto intro:hoaret.Skip)
next
case Assign show ?case by (auto intro:hoaret.Assign)
next
case Seq thus ?case by (auto intro:hoaret.Seq)
next
case If thus ?case by (auto intro:hoaret.If hoaret.conseq)
next
case (While b c)
let ?w = "WHILE b DO c"
let ?T = "Its b c"
have 1: "\<forall>s. wp\<^sub>t ?w Q s \<longrightarrow> wp\<^sub>t ?w Q s \<and> (\<exists>n. Its b c s n)"
unfolding wpt_def by (metis WHILE_Its)
let ?R = "\<lambda>n s'. wp\<^sub>t ?w Q s' \<and> (\<exists>n'<n. ?T s' n')"
have "\<forall>s. wp\<^sub>t ?w Q s \<and> bval b s \<and> ?T s n \<longrightarrow> 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) \<Rightarrow> 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) \<Rightarrow> s'" "(?w,s') \<Rightarrow> 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
qed
note 2 = hoaret.While[OF strengthen_pre[OF this While.IH]]
have "\<forall>s. wp\<^sub>t ?w Q s \<and> \<not> bval b s \<longrightarrow> Q s"
by (auto simp add:wpt_def)
with 1 2 show ?case by (rule conseq)
qed

theorem hoaret_complete: "\<Turnstile>\<^sub>t {P}c{Q} \<Longrightarrow> \<turnstile>\<^sub>t {P}c{Q}"
apply(rule strengthen_pre[OF _ wpt_is_pre])
apply(auto simp: hoare_tvalid_def wpt_def)
done

corollary hoaret_sound_complete: "\<turnstile>\<^sub>t {P}c{Q} \<longleftrightarrow> \<Turnstile>\<^sub>t {P}c{Q}"
by (metis hoaret_sound hoaret_complete)

paragraph "Extra:"

lemma total_imp_partial: "\<turnstile>\<^sub>t {P} c {Q} \<Longrightarrow> \<turnstile> {P} c {Q}"
proof -
assume "\<turnstile>\<^sub>t {P} c {Q}"
then have "\<Turnstile>\<^sub>t {P} c {Q}" by (auto simp: hoaret_sound_complete)
then have "\<Turnstile> {P} c {Q}"
unfolding partial_hoare_valid_def hoare_tvalid_def using big_step_determ by blast
thus "\<turnstile> {P} c {Q}"
by (simp add: partial_hoare_complete)
qed

paragraph "Program:"

definition neq :: "aexp \<Rightarrow> aexp \<Rightarrow> bexp" where
"neq a\<^sub>1 a\<^sub>2 \<equiv> Not (And (Not (Less a\<^sub>1 a\<^sub>2)) (Not (Less a\<^sub>2 a\<^sub>1)))"

definition "EGGT :: com \<equiv>
''old_r'' ::= V ''a'';;
''r'' ::= V ''b'';;

''old_s'' ::= N 1;;
''s'' ::= N 0;;

''old_t'' ::= N 0;;
''t'' ::= N 1;;

WHILE neq (V ''r'') (N 0) DO (
''quotient'' ::= Div (V ''old_r'') (V ''r'');;

''tmp'' ::= V ''old_r'';;
''old_r'' ::= V ''r'';;
''r'' ::= Minus (V ''tmp'') (Mul (V ''quotient'') (V ''r''));;

''tmp'' ::= V ''old_s'';;
''old_s'' ::= V ''s'';;
''s'' ::= Minus (V ''tmp'') (Mul (V ''quotient'') (V ''s''));;

''tmp'' ::= V ''old_t'';;
''old_t'' ::= V ''t'';;
''t'' ::= Minus (V ''tmp'') (Mul (V ''quotient'') (V ''t''))
)"

consts pre :: "acom \<Rightarrow> assn \<Rightarrow> assn"

consts vc :: "acom \<Rightarrow> assn \<Rightarrow> bool"

end```

Template File

```theory Submission
imports Defs
begin

unbundle ACOM

fun pre :: "acom \<Rightarrow> assn \<Rightarrow> assn"  where
"pre _ = undefined"

fun vc :: "acom \<Rightarrow> assn \<Rightarrow> bool"  where
"vc _ = undefined"

lemma vc_sound: "vc C Q \<Longrightarrow> \<turnstile>\<^sub>t {pre C Q} strip C {Q}"
sorry

corollary vc_sound':
"\<lbrakk> vc C Q; \<forall>s. P s \<longrightarrow> pre C Q s \<rbrakk> \<Longrightarrow> \<turnstile>\<^sub>t {P} strip C {Q}"
by (metis strengthen_pre vc_sound)

theorem EGGT_correct:  "\<turnstile>\<^sub>t
{\<lambda>s. s = s\<^sub>0 \<and> s\<^sub>0 ''a'' > 0 \<and> s\<^sub>0 ''b'' > 0}
EGGT
{\<lambda>s. s ''old_r'' = gcd (s\<^sub>0 ''a'') (s\<^sub>0 ''b'') \<and> gcd (s\<^sub>0 ''a'') (s\<^sub>0 ''b'') = s\<^sub>0 ''a'' * s ''old_s'' + s\<^sub>0 ''b'' * s ''old_t'' }"
sorry

corollary EGGT_partial: "\<turnstile> {\<lambda>s. s = s\<^sub>0 \<and> s\<^sub>0 ''a'' > 0 \<and> s\<^sub>0 ''b'' > 0}
EGGT
{\<lambda>s. s ''old_r'' = gcd (s\<^sub>0 ''a'') (s\<^sub>0 ''b'') \<and> gcd (s\<^sub>0 ''a'') (s\<^sub>0 ''b'') = s\<^sub>0 ''a'' * s ''old_s'' + s\<^sub>0 ''b'' * s ''old_t'' }"
by (rule total_imp_partial[OF EGGT_correct])

end```

Check File

```theory Check
imports Submission
begin

lemma vc_sound: "vc C Q \<Longrightarrow> \<turnstile>\<^sub>t {pre C Q} strip C {Q}"
by (rule Submission.vc_sound)

theorem EGGT_correct: "\<turnstile>\<^sub>t
{\<lambda>s. s = s\<^sub>0 \<and> s\<^sub>0 ''a'' > 0 \<and> s\<^sub>0 ''b'' > 0}
EGGT
{\<lambda>s. s ''old_r'' = gcd (s\<^sub>0 ''a'') (s\<^sub>0 ''b'') \<and> gcd (s\<^sub>0 ''a'') (s\<^sub>0 ''b'') = s\<^sub>0 ''a'' * s ''old_s'' + s\<^sub>0 ''b'' * s ''old_t'' }"
by (rule Submission.EGGT_correct)

end```

Terms and Conditions