author | wenzelm |
Sun, 02 Oct 2016 14:07:43 +0200 | |
changeset 63992 | 3aa9837d05c7 |
parent 63538 | d7b5e2a222c2 |
child 67019 | 7a3724078363 |
permissions | -rw-r--r-- |
63070 | 1 |
(* Author: Tobias Nipkow *) |
2 |
||
63538
d7b5e2a222c2
added new vcg based on existentially quantified while-rule
nipkow
parents:
63070
diff
changeset
|
3 |
theory Hoare_Total_EX |
d7b5e2a222c2
added new vcg based on existentially quantified while-rule
nipkow
parents:
63070
diff
changeset
|
4 |
imports Hoare |
d7b5e2a222c2
added new vcg based on existentially quantified while-rule
nipkow
parents:
63070
diff
changeset
|
5 |
begin |
63070 | 6 |
|
63538
d7b5e2a222c2
added new vcg based on existentially quantified while-rule
nipkow
parents:
63070
diff
changeset
|
7 |
subsubsection "Hoare Logic for Total Correctness --- \<open>nat\<close>-Indexed Invariant" |
63070 | 8 |
|
9 |
text{* This is the standard set of rules that you find in many publications. |
|
10 |
The While-rule is different from the one in Concrete Semantics in that the |
|
11 |
invariant is indexed by natural numbers and goes down by 1 with |
|
12 |
every iteration. The completeness proof is easier but the rule is harder |
|
13 |
to apply in program proofs. *} |
|
14 |
||
15 |
definition hoare_tvalid :: "assn \<Rightarrow> com \<Rightarrow> assn \<Rightarrow> bool" |
|
16 |
("\<Turnstile>\<^sub>t {(1_)}/ (_)/ {(1_)}" 50) where |
|
17 |
"\<Turnstile>\<^sub>t {P}c{Q} \<longleftrightarrow> (\<forall>s. P s \<longrightarrow> (\<exists>t. (c,s) \<Rightarrow> t \<and> Q t))" |
|
18 |
||
19 |
inductive |
|
20 |
hoaret :: "assn \<Rightarrow> com \<Rightarrow> assn \<Rightarrow> bool" ("\<turnstile>\<^sub>t ({(1_)}/ (_)/ {(1_)})" 50) |
|
21 |
where |
|
22 |
||
23 |
Skip: "\<turnstile>\<^sub>t {P} SKIP {P}" | |
|
24 |
||
25 |
Assign: "\<turnstile>\<^sub>t {\<lambda>s. P(s[a/x])} x::=a {P}" | |
|
26 |
||
27 |
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}" | |
|
28 |
||
29 |
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> |
|
30 |
\<Longrightarrow> \<turnstile>\<^sub>t {P} IF b THEN c\<^sub>1 ELSE c\<^sub>2 {Q}" | |
|
31 |
||
32 |
While: |
|
33 |
"\<lbrakk> \<And>n::nat. \<turnstile>\<^sub>t {P (Suc n)} c {P n}; |
|
34 |
\<forall>n s. P (Suc n) s \<longrightarrow> bval b s; \<forall>s. P 0 s \<longrightarrow> \<not> bval b s \<rbrakk> |
|
35 |
\<Longrightarrow> \<turnstile>\<^sub>t {\<lambda>s. \<exists>n. P n s} WHILE b DO c {P 0}" | |
|
36 |
||
37 |
conseq: "\<lbrakk> \<forall>s. P' s \<longrightarrow> P s; \<turnstile>\<^sub>t {P}c{Q}; \<forall>s. Q s \<longrightarrow> Q' s \<rbrakk> \<Longrightarrow> |
|
38 |
\<turnstile>\<^sub>t {P'}c{Q'}" |
|
39 |
||
40 |
text{* Building in the consequence rule: *} |
|
41 |
||
42 |
lemma strengthen_pre: |
|
43 |
"\<lbrakk> \<forall>s. P' s \<longrightarrow> P s; \<turnstile>\<^sub>t {P} c {Q} \<rbrakk> \<Longrightarrow> \<turnstile>\<^sub>t {P'} c {Q}" |
|
44 |
by (metis conseq) |
|
45 |
||
46 |
lemma weaken_post: |
|
47 |
"\<lbrakk> \<turnstile>\<^sub>t {P} c {Q}; \<forall>s. Q s \<longrightarrow> Q' s \<rbrakk> \<Longrightarrow> \<turnstile>\<^sub>t {P} c {Q'}" |
|
48 |
by (metis conseq) |
|
49 |
||
50 |
lemma Assign': "\<forall>s. P s \<longrightarrow> Q(s[a/x]) \<Longrightarrow> \<turnstile>\<^sub>t {P} x ::= a {Q}" |
|
51 |
by (simp add: strengthen_pre[OF _ Assign]) |
|
52 |
||
53 |
text{* The soundness theorem: *} |
|
54 |
||
55 |
theorem hoaret_sound: "\<turnstile>\<^sub>t {P}c{Q} \<Longrightarrow> \<Turnstile>\<^sub>t {P}c{Q}" |
|
56 |
proof(unfold hoare_tvalid_def, induction rule: hoaret.induct) |
|
57 |
case (While P c b) |
|
58 |
{ |
|
59 |
fix n s |
|
60 |
have "\<lbrakk> P n s \<rbrakk> \<Longrightarrow> \<exists>t. (WHILE b DO c, s) \<Rightarrow> t \<and> P 0 t" |
|
61 |
proof(induction "n" arbitrary: s) |
|
62 |
case 0 thus ?case using While.hyps(3) WhileFalse by blast |
|
63 |
next |
|
64 |
case (Suc n) |
|
65 |
thus ?case by (meson While.IH While.hyps(2) WhileTrue) |
|
66 |
qed |
|
67 |
} |
|
68 |
thus ?case by auto |
|
69 |
next |
|
70 |
case If thus ?case by auto blast |
|
71 |
qed fastforce+ |
|
72 |
||
73 |
||
74 |
definition wpt :: "com \<Rightarrow> assn \<Rightarrow> assn" ("wp\<^sub>t") where |
|
75 |
"wp\<^sub>t c Q = (\<lambda>s. \<exists>t. (c,s) \<Rightarrow> t \<and> Q t)" |
|
76 |
||
77 |
lemma [simp]: "wp\<^sub>t SKIP Q = Q" |
|
78 |
by(auto intro!: ext simp: wpt_def) |
|
79 |
||
80 |
lemma [simp]: "wp\<^sub>t (x ::= e) Q = (\<lambda>s. Q(s(x := aval e s)))" |
|
81 |
by(auto intro!: ext simp: wpt_def) |
|
82 |
||
83 |
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)" |
|
84 |
unfolding wpt_def |
|
85 |
apply(rule ext) |
|
86 |
apply auto |
|
87 |
done |
|
88 |
||
89 |
lemma [simp]: |
|
90 |
"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)" |
|
91 |
apply(unfold wpt_def) |
|
92 |
apply(rule ext) |
|
93 |
apply auto |
|
94 |
done |
|
95 |
||
96 |
||
97 |
text{* Function @{text wpw} computes the weakest precondition of a While-loop |
|
98 |
that is unfolded a fixed number of times. *} |
|
99 |
||
100 |
fun wpw :: "bexp \<Rightarrow> com \<Rightarrow> nat \<Rightarrow> assn \<Rightarrow> assn" where |
|
101 |
"wpw b c 0 Q s = (\<not> bval b s \<and> Q s)" | |
|
102 |
"wpw b c (Suc n) Q s = (bval b s \<and> (\<exists>s'. (c,s) \<Rightarrow> s' \<and> wpw b c n Q s'))" |
|
103 |
||
104 |
lemma WHILE_Its: "(WHILE b DO c,s) \<Rightarrow> t \<Longrightarrow> Q t \<Longrightarrow> \<exists>n. wpw b c n Q s" |
|
105 |
proof(induction "WHILE b DO c" s t rule: big_step_induct) |
|
106 |
case WhileFalse thus ?case using wpw.simps(1) by blast |
|
107 |
next |
|
108 |
case WhileTrue thus ?case using wpw.simps(2) by blast |
|
109 |
qed |
|
110 |
||
111 |
lemma wpt_is_pre: "\<turnstile>\<^sub>t {wp\<^sub>t c Q} c {Q}" |
|
112 |
proof (induction c arbitrary: Q) |
|
113 |
case SKIP show ?case by (auto intro:hoaret.Skip) |
|
114 |
next |
|
115 |
case Assign show ?case by (auto intro:hoaret.Assign) |
|
116 |
next |
|
117 |
case Seq thus ?case by (auto intro:hoaret.Seq) |
|
118 |
next |
|
119 |
case If thus ?case by (auto intro:hoaret.If hoaret.conseq) |
|
120 |
next |
|
121 |
case (While b c) |
|
122 |
let ?w = "WHILE b DO c" |
|
123 |
have c1: "\<forall>s. wp\<^sub>t ?w Q s \<longrightarrow> (\<exists>n. wpw b c n Q s)" |
|
124 |
unfolding wpt_def by (metis WHILE_Its) |
|
125 |
have c3: "\<forall>s. wpw b c 0 Q s \<longrightarrow> Q s" by simp |
|
126 |
have w2: "\<forall>n s. wpw b c (Suc n) Q s \<longrightarrow> bval b s" by simp |
|
127 |
have w3: "\<forall>s. wpw b c 0 Q s \<longrightarrow> \<not> bval b s" by simp |
|
128 |
{ fix n |
|
129 |
have 1: "\<forall>s. wpw b c (Suc n) Q s \<longrightarrow> (\<exists>t. (c, s) \<Rightarrow> t \<and> wpw b c n Q t)" |
|
130 |
by simp |
|
131 |
note strengthen_pre[OF 1 While.IH[of "wpw b c n Q", unfolded wpt_def]] |
|
132 |
} |
|
133 |
from conseq[OF c1 hoaret.While[OF this w2 w3] c3] |
|
134 |
show ?case . |
|
135 |
qed |
|
136 |
||
137 |
theorem hoaret_complete: "\<Turnstile>\<^sub>t {P}c{Q} \<Longrightarrow> \<turnstile>\<^sub>t {P}c{Q}" |
|
138 |
apply(rule strengthen_pre[OF _ wpt_is_pre]) |
|
139 |
apply(auto simp: hoare_tvalid_def wpt_def) |
|
140 |
done |
|
141 |
||
142 |
corollary hoaret_sound_complete: "\<turnstile>\<^sub>t {P}c{Q} \<longleftrightarrow> \<Turnstile>\<^sub>t {P}c{Q}" |
|
143 |
by (metis hoaret_sound hoaret_complete) |
|
144 |
||
145 |
end |