-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSimulation.thy
346 lines (301 loc) · 13.1 KB
/
Simulation.thy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
(*
* Copyright 2014, NICTA
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(NICTA_BSD)
*)
(*
A general calculus of refinement in Isabelle.
*)
chapter "Refinement"
theory Simulation
imports "~~/src/HOL/Main"
begin
text {*
A data type is a collection of three functions on three basic types.
The three basic types are the private state space @{typ 'a}, the observable
state space @{typ 'b} and the operations @{typ 'j}.
The three functions are the initialisation @{term "Init"} which (potentially
nondeterministically) produces a private state space from an observable one,
the finalisation @{term Fin} which projects the observable part of
the state space out of the private one, and finally @{term Step} that gives
the (potentially nondeterministic) transition relation on the private state
space for each operation in @{typ 'j}.
In the simple case, the private state space is something like a
tuple @{typ "'a \<times> 'b"} fully containing the observable part such
that @{term Fin} just becomes the projection @{term snd}, and @{term
"Init s"} constructs an additional private part, e.g. just
@{term "{(f x, x)}"}.
Hoare triples on the system and refinement are defined over the observable
part of the state.
*}
record ('a,'b,'j) data_type =
Init :: "'b \<Rightarrow> 'a set"
Fin :: "'a \<Rightarrow> 'b"
Step :: "'j \<Rightarrow> ('a \<times> 'a) set"
text {*
A sequence of operations over a transition relation @{term \<delta>} is executed
by applying the relation repeatedly.
*}
definition
steps :: "('j \<Rightarrow> ('a \<times> 'a) set) \<Rightarrow> 'a set \<Rightarrow> 'j list \<Rightarrow> 'a set" where
"steps \<delta> \<equiv> foldl (\<lambda>S j. \<delta> j `` S)"
text {*
The sequence of operations in the data type is then executed
in an initial state by initialising the private state, executing
the transition relation over this private state, and finally
projecting back out the set of final, observable states.
*}
definition
execution :: "('a,'b,'j) data_type \<Rightarrow> 'b \<Rightarrow> 'j list \<Rightarrow> 'b set" where
"execution A s js \<equiv> Fin A ` steps (Step A) (Init A s) js"
text {*
A Hoare triple over a list of operations in the data type is
the usual: given a state in the pre-condition, all resulting states
of the execution must be in the post-condition:
*}
definition
hoare_triple :: "('a,'b,'j) data_type \<Rightarrow> 'b set \<Rightarrow> 'j list \<Rightarrow> 'b set \<Rightarrow> bool"
where
"hoare_triple A P js Q \<equiv> \<forall>s \<in> P. execution A s js \<subseteq> Q"
text {*
Refinement is defined by saying that all concrete behaviours are contained in
their corresponding abstract ones. Only the private state spaces of the
data type may differ.
*}
definition
refines :: "('c,'b,'j) data_type \<Rightarrow> ('a,'b,'j) data_type \<Rightarrow> bool" (infix "\<sqsubseteq>" 60)
where
"C \<sqsubseteq> A \<equiv> \<forall>js s. execution C s js \<subseteq> execution A s js"
text {*
Alternatively, one may say that all Hoare triples proved on the abstract data
type are true for the concrete one.
*}
lemma hoare_triple_refinement:
"C \<sqsubseteq> A = (\<forall>P Q js. hoare_triple A P js Q \<longrightarrow> hoare_triple C P js Q)"
by (simp add: refines_def hoare_triple_def) blast
-- "composing two relations"
definition
rel_semi :: "('a \<times> 'b) set \<Rightarrow> ('b \<times> 'c) set \<Rightarrow> ('a \<times> 'c) set" (infixl ";;;" 65)
where
"A ;;; B \<equiv> A O B"
text {*
Refinement is a global property over all executions and/or all
hoare triples. As this is hard to show, we define the weaker concept
of forward simulation.
*}
definition
fw_sim :: "('a \<times> 'c) set \<Rightarrow> ('c,'b,'j) data_type \<Rightarrow> ('a,'b,'j) data_type \<Rightarrow> bool"
where
"fw_sim R C A \<equiv> (\<forall>s. Init C s \<subseteq> R `` Init A s) \<and>
(\<forall>j. R ;;; Step C j \<subseteq> Step A j ;;; R) \<and>
(\<forall>s s'. (s,s') \<in> R \<longrightarrow> Fin C s' = Fin A s)"
definition
fw_simulates :: "('c,'b,'j) data_type \<Rightarrow> ('a,'b,'j) data_type \<Rightarrow> bool" (infixl "\<sqsubseteq>\<^sub>F" 50)
where
"C \<sqsubseteq>\<^sub>F A \<equiv> \<exists>R. fw_sim R C A"
lemma fw_sim_steps:
assumes steps: "t' \<in> steps (Step C) S' js" "S' \<subseteq> R `` S"
assumes sim: "fw_sim R C A"
shows "\<exists>t \<in> steps (Step A) S js. (t,t') \<in> R" using steps
proof (induct js arbitrary: S' S)
case Nil
thus ?case by (simp add: steps_def) blast
next
case (Cons j js)
hence "t' \<in> steps (Step C) (Step C j `` S') js"
by (clarsimp simp: steps_def)
moreover {
from Cons.prems
have "S' \<subseteq> R `` S" by simp
moreover
from sim
have "R ;;; Step C j \<subseteq> Step A j ;;; R" by (simp add: fw_sim_def)
ultimately
have "Step C j `` S' \<subseteq> R `` (Step A j `` S)"
by (simp add: rel_semi_def) blast
}
ultimately
show ?case using Cons.hyps
by (auto simp: steps_def)
qed
lemma sim_imp_refines:
"C \<sqsubseteq>\<^sub>F A \<Longrightarrow> C \<sqsubseteq> A"
apply (clarsimp simp: refines_def execution_def fw_simulates_def)
apply (rename_tac t)
apply (drule fw_sim_steps)
prefer 2
apply assumption
apply (simp add: fw_sim_def)
apply blast
apply clarsimp
apply (erule rev_image_eqI)
apply (simp add: fw_sim_def)
done
text {*
To further aid proofs, we define (private) invariants on data types.
Private invariants are properties that are true throughout execution
on the private state space of the state type. The purpose is to exploit
these properties while showing forward simulation.
*}
definition
invariant_holds :: "('a,'b,'j) data_type \<Rightarrow> 'a set \<Rightarrow> bool" (infix "\<Turnstile>" 60)
where
"D \<Turnstile> I \<equiv> (\<forall>s. Init D s \<subseteq> I) \<and> (\<forall>j. Step D j `` I \<subseteq> I)"
lemma invariant_T [iff]: "D \<Turnstile> UNIV"
by (simp add: invariant_holds_def)
lemma invariantI:
"\<lbrakk> \<forall>s. Init D s \<subseteq> I; \<forall>j. Step D j `` I \<subseteq> I \<rbrakk> \<Longrightarrow> D \<Turnstile> I"
by (simp add: invariant_holds_def)
lemma invariant_CollectI [intro?]:
assumes init: "\<And>s a. s \<in> Init D a \<Longrightarrow> I s"
assumes step: "\<And>j s s'. \<lbrakk> I s; (s,s') \<in> Step D j \<rbrakk> \<Longrightarrow> I s'"
shows "D \<Turnstile> Collect I"
proof (rule invariantI)
show "\<forall>a. Init D a \<subseteq> Collect I" by (fast intro: init)
next
show "\<forall>j. Step D j `` Collect I \<subseteq> Collect I"
by (auto simp add: Image_def intro: step)
qed
lemma invariant_conjI:
"D \<Turnstile> P \<Longrightarrow> D \<Turnstile> Q \<Longrightarrow> D \<Turnstile> P \<inter> Q"
by (simp add: invariant_holds_def) blast
lemma invariant_conjI2:
"\<lbrakk> D \<Turnstile> I; \<And>s. Init D s \<subseteq> I \<Longrightarrow> Init D s \<subseteq> J;
\<forall>j. Step D j `` (I \<inter> J) \<subseteq> J \<rbrakk> \<Longrightarrow> D \<Turnstile> I \<inter> J"
by (simp add: invariant_holds_def) blast
text {*
We can now define forward simulation with an invariant. The proof
obligation for the step and final case in the correspondence proof
can now assume that the invariant holds. The invariant itself can be
shown separately.
*}
definition
LI :: "('a,'b,'j) data_type \<Rightarrow> ('c,'b,'j) data_type \<Rightarrow> ('a \<times> 'c) set \<Rightarrow> ('a \<times> 'c) set \<Rightarrow> bool"
where
"LI A C R I \<equiv> (\<forall>s. Init C s \<subseteq> R `` Init A s) \<and>
(\<forall>j. (R \<inter> I) ;;; Step C j \<subseteq> Step A j ;;; R) \<and>
(\<forall>s s'. (s,s') \<in> R \<inter> I \<longrightarrow> Fin C s' = Fin A s)"
lemma LI_fw_sim:
assumes ia: "A \<Turnstile> I\<^sub>a" and ic: "C \<Turnstile> I\<^sub>c" and li: "LI A C r (I\<^sub>a \<times> I\<^sub>c)"
shows "fw_sim (r \<inter> I\<^sub>a \<times> I\<^sub>c) C A"
proof -
from li have
init: "\<forall>s. Init C s \<subseteq> r `` Init A s" and
step: "\<forall>j. (r \<inter> (I\<^sub>a \<times> I\<^sub>c)) ;;; Step C j \<subseteq> Step A j ;;; r" and
fin: "(\<forall>s s'. (s,s') \<in> r \<inter> (I\<^sub>a \<times> I\<^sub>c) \<longrightarrow> Fin C s' = Fin A s)"
by (auto simp: LI_def)
from ia have "\<forall>s. (r \<inter> (UNIV \<times> I\<^sub>c) ) `` Init A s = (r \<inter> (I\<^sub>a \<times> I\<^sub>c)) `` Init A s"
by (simp add: invariant_holds_def, blast)
moreover from init ic have "\<forall>s. Init C s \<subseteq> (r \<inter> (UNIV \<times> I\<^sub>c)) `` Init A s"
by (simp add: invariant_holds_def, blast)
ultimately have initI: "\<forall>s. Init C s \<subseteq> (r \<inter> (I\<^sub>a \<times> I\<^sub>c)) `` Init A s" by simp
moreover {
fix j
from step have "r \<inter> (I\<^sub>a \<times> I\<^sub>c) ;;; Step C j \<subseteq> Step A j ;;; r"..
also
have "r \<inter> (I\<^sub>a \<times> I\<^sub>c) = ((UNIV \<times> I\<^sub>a) \<inter> Id) ;;; r ;;; ((I\<^sub>c \<times> UNIV) \<inter> Id)"
(is "_ = ?I\<^sub>a ;;; r ;;; ?I\<^sub>c")
by (simp add: rel_semi_def, blast)
finally
have "?I\<^sub>a ;;; r ;;; ?I\<^sub>c ;;; Step C j \<subseteq> ?I\<^sub>a ;;; Step A j ;;; r"
by (simp add: rel_semi_def, blast)
also
from ia have "\<dots> \<subseteq> Step A j ;;; ?I\<^sub>a ;;; r"
by (simp add: invariant_holds_def rel_semi_def, blast)
finally
have "?I\<^sub>a ;;; r ;;; ?I\<^sub>c ;;; Step C j;;; ?I\<^sub>c \<subseteq> Step A j ;;; ?I\<^sub>a ;;; r ;;; ?I\<^sub>c"
by (simp add: rel_semi_def, blast)
also
from ic
have "?I\<^sub>a ;;; r ;;; ?I\<^sub>c ;;; Step C j;;; ?I\<^sub>c = ?I\<^sub>a ;;; r ;;; ?I\<^sub>c ;;; Step C j"
by (simp add: invariant_holds_def rel_semi_def, blast)
finally
have "r \<inter> (I\<^sub>a \<times> I\<^sub>c) ;;; Step C j \<subseteq> Step A j ;;; r \<inter> (I\<^sub>a \<times> I\<^sub>c)"
by (simp add: rel_semi_def, blast)
}
ultimately show "fw_sim (r \<inter> I\<^sub>a \<times> I\<^sub>c) C A" using fin
by (simp add: fw_sim_def)
qed
lemma weaken_LI:
assumes LI: "LI A C R I'" and weaker: "I \<subseteq> I'" shows "LI A C R I"
proof -
from weaker have step: "\<And>j. R \<inter> I ;;; Step C j \<subseteq> R \<inter> I' ;;; Step C j"
by (fastforce simp: rel_semi_def relcomp_def)
from weaker have fin: "\<And>S. S \<in> R \<inter> I \<Longrightarrow> S \<in> R \<inter> I'" by fastforce
from subset_trans[OF step] fin LI show ?thesis by (clarsimp simp: LI_def)
qed
lemma fw_sim_eq_LI: "fw_sim r C A = LI A C r UNIV"
by (simp add: fw_sim_def LI_def)
lemma fw_sim_LI: "fw_sim r C A \<Longrightarrow> LI A C r I"
by (simp add: fw_sim_eq_LI weaken_LI[where I'=UNIV])
lemma L_invariantI:
assumes "A \<Turnstile> I\<^sub>a" and "C \<Turnstile> I\<^sub>c" and "LI A C r (I\<^sub>a \<times> I\<^sub>c)"
shows "C \<sqsubseteq>\<^sub>F A"
using assms
by (simp add: fw_simulates_def, rule_tac x="r \<inter> I\<^sub>a \<times> I\<^sub>c" in exI,
simp add: LI_fw_sim)
lemma refinement_refl[simp]:
"A \<sqsubseteq> A"
by (simp add: refines_def)
lemma refinement_trans [trans]:
"\<lbrakk>C \<sqsubseteq> B; B \<sqsubseteq> A\<rbrakk> \<Longrightarrow> C \<sqsubseteq> A"
by (simp add: refines_def) blast
lemma fw_inv_transport:
"\<lbrakk> A \<Turnstile> I\<^sub>a; C \<Turnstile> I\<^sub>c; LI A C R (I\<^sub>a \<times> I\<^sub>c) \<rbrakk> \<Longrightarrow> C \<Turnstile> {s'. \<exists>s. (s,s') \<in> R \<and> s \<in> I\<^sub>a \<and> s' \<in> I\<^sub>c}"
apply (clarsimp simp: LI_def invariant_holds_def)
apply (rule conjI)
apply (rule allI)
apply clarsimp
apply (subgoal_tac "x \<in> (R `` Init A s)")
prefer 2
apply fastforce
apply blast
apply clarsimp
apply (erule_tac x=j in allE)+
apply (clarsimp simp: rel_semi_def)
apply (subgoal_tac "(s,x) \<in> Step A j O R")
prefer 2
apply blast
apply blast
done
lemma fw_sim_refl:
"fw_sim Id A A"
apply (simp add: fw_sim_def rel_semi_def)
done
lemma fw_simulates_refl[simp]:
"A \<sqsubseteq>\<^sub>F A"
apply (simp add: fw_simulates_def fw_sim_refl exI[where x="Id"])
done
lemma fw_sim_trans:
"\<lbrakk>fw_sim Q C B; fw_sim R B A\<rbrakk> \<Longrightarrow> fw_sim (R O Q) C A"
apply (clarsimp simp: fw_sim_def)
apply (intro conjI)
apply clarsimp
apply (rename_tac s x)
apply (erule_tac x="s" in allE)
apply (drule set_mp)
apply assumption
apply clarsimp
apply (erule_tac x="s" in allE)
apply (drule set_mp)
apply assumption
apply blast
apply (clarsimp simp: rel_semi_def)
apply (rename_tac j z' x y z)
apply (erule_tac x="j" in allE)+
apply (drule_tac x="(y, z')" in set_mp)
apply blast
apply clarsimp
apply (rename_tac j x z x' y' z')
apply (drule_tac x="(x, y')" in set_mp)
apply auto
done
lemma fw_simulates_trans:
"\<lbrakk>C \<sqsubseteq>\<^sub>F B; B \<sqsubseteq>\<^sub>F A\<rbrakk> \<Longrightarrow> C \<sqsubseteq>\<^sub>F A"
apply (auto simp: fw_simulates_def dest: fw_sim_trans)
done
end