-
Notifications
You must be signed in to change notification settings - Fork 108
/
BCorres_UL.thy
305 lines (241 loc) · 13.1 KB
/
BCorres_UL.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
(*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*)
theory BCorres_UL
imports
Monads.Nondet_VCG
Crunch_Instances_NonDet
begin
definition s_bcorres_underlying where
"s_bcorres_underlying t f g s \<equiv> (\<lambda>(x,y). (x, t y)) ` (fst (f s)) \<subseteq> (fst (g (t s)))"
definition bcorres_underlying where
"bcorres_underlying t f g \<equiv> \<forall>s. s_bcorres_underlying t f g s"
lemma wpc_helper_bcorres:
"bcorres_underlying t f g \<Longrightarrow> wpc_helper P Q (bcorres_underlying t f g)"
by (simp add: wpc_helper_def split: prod.split)
lemma wpc_helper_s_bcorres:
"s_bcorres_underlying t f g s \<Longrightarrow> wpc_helper P Q (s_bcorres_underlying t f g s)"
by (simp add: wpc_helper_def split: prod.split)
wpc_setup "\<lambda>f. bcorres_underlying t f g" wpc_helper_bcorres
wpc_setup "\<lambda>f. s_bcorres_underlying t f g s" wpc_helper_bcorres
lemma s_bcorres_underlying_split[wp_split]:
"(\<And>r s'. (r,s') \<in> fst (f s) \<Longrightarrow> (s_bcorres_underlying t (g r) (g' r) s')) \<Longrightarrow>
s_bcorres_underlying t f f' s \<Longrightarrow>
s_bcorres_underlying t (f >>= g) (f' >>= g') s"
by (clarsimp simp: s_bcorres_underlying_def bind_def) force
lemma bcorres_underlying_split[wp_split]:
"(\<And>r. (bcorres_underlying t (g r) (g' r))) \<Longrightarrow>
bcorres_underlying t f f' \<Longrightarrow>
bcorres_underlying t (f >>= g) (f' >>= g')"
by (simp add: bcorres_underlying_def s_bcorres_underlying_split)
lemma get_s_bcorres_underlying[wp]:
"s_bcorres_underlying t (f s) (f' (t s)) s \<Longrightarrow> s_bcorres_underlying t (get >>= f) (get >>= f') s"
by (simp add: gets_def s_bcorres_underlying_def get_def bind_def return_def)
lemma get_bcorres[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' (t x))) \<Longrightarrow> bcorres_underlying t (get >>= f) (get >>= f')"
by (simp add: bcorres_underlying_def get_s_bcorres_underlying)
lemma gets_s_bcorres_underlying[wp]:
"x' (t s) = x s \<Longrightarrow> s_bcorres_underlying t (gets x) (gets x') s"
by (simp add: s_bcorres_underlying_def gets_def get_def bind_def return_def)
lemma gets_bcorres_underlying[wp]:
"(\<And>s. x' (t s) = x s) \<Longrightarrow> bcorres_underlying t (gets x) (gets x')"
by (simp add: bcorres_underlying_def gets_s_bcorres_underlying)
lemma gets_map_bcorres_underlying[wp]:
"(\<And>s. f' (t s) p = f s p) \<Longrightarrow> bcorres_underlying t (gets_map f p) (gets_map f' p)"
by (simp add: gets_map_def bcorres_underlying_def s_bcorres_underlying_def simpler_gets_def
bind_def assert_opt_def fail_def return_def
split: option.splits)
lemma gets_bcorres_underlying':
"(\<And>xa. bcorres_underlying t (f (x xa)) (f' (x' (t xa)))) \<Longrightarrow>
bcorres_underlying t (gets x >>= f) (gets x' >>= f')"
by (wpsimp simp: gets_def)
lemma assert_bcorres_underlying[wp]:
"f = f' \<Longrightarrow> bcorres_underlying t (assert f) (assert f')"
by (simp add: assert_def bcorres_underlying_def return_def s_bcorres_underlying_def fail_def)
lemma return_bcorres[wp]:
"bcorres_underlying t (return x) (return x)"
by (simp add:return_def bcorres_underlying_def s_bcorres_underlying_def)
lemma drop_sbcorres_underlying:
"bcorres_underlying t f g \<Longrightarrow> s_bcorres_underlying t f g s"
by (simp add: bcorres_underlying_def)
lemma use_sbcorres_underlying:
"(\<And>s. s_bcorres_underlying t f g s) \<Longrightarrow> bcorres_underlying t f g"
by (simp add: bcorres_underlying_def)
lemma bcorres_underlying_throwError[wp]:
"bcorres_underlying t (throwError a) (throwError a)"
by (wpsimp simp: throwError_def)
lemma s_bcorres_underlying_splitE[wp_split]:
"(\<And>r s'. (Inr r,s') \<in> fst (f s) \<Longrightarrow> s_bcorres_underlying t (g r) (g' r) s') \<Longrightarrow>
s_bcorres_underlying t f f' s \<Longrightarrow>
s_bcorres_underlying t (f >>=E g) (f' >>=E g') s"
by (wpsimp simp: bindE_def lift_def split: sum.splits | rule conjI drop_sbcorres_underlying)+
lemma get_s_bcorres_underlyingE[wp]:
"s_bcorres_underlying t (f s) (f' (t s)) s \<Longrightarrow>
s_bcorres_underlying t (liftE get >>=E f) (liftE get >>=E f') s"
by (simp add: gets_def s_bcorres_underlying_def get_def bindE_def bind_def return_def liftE_def lift_def)
lemma bcorres_underlying_splitE[wp_split]:
"(\<And>r. bcorres_underlying t (g r) (g' r)) \<Longrightarrow>
bcorres_underlying t f f' \<Longrightarrow>
bcorres_underlying t (f >>=E g) (f' >>=E g')"
by (simp add: bcorres_underlying_def s_bcorres_underlying_splitE)
lemmas return_s_bcorres_underlying[wp] = drop_sbcorres_underlying[OF return_bcorres]
lemma liftE_s_bcorres_underlying[wp]:
"s_bcorres_underlying t f f' s \<Longrightarrow> s_bcorres_underlying t (liftE f) (liftE f') s"
by (wpsimp simp: liftE_def)
lemma liftE_bcorres_underlying[wp]:
"bcorres_underlying t f f' \<Longrightarrow> bcorres_underlying t (liftE f) (liftE f')"
by (simp add: bcorres_underlying_def liftE_s_bcorres_underlying)
lemma returnOk_bcorres_underlying[wp]:
"bcorres_underlying t (returnOk x) (returnOk x)"
by (wpsimp simp: returnOk_def)
lemma whenE_s_bcorres_underlying[wp]:
"\<lbrakk> \<lbrakk>P = P'; P\<rbrakk> \<Longrightarrow> s_bcorres_underlying t f f' s; P = P' \<rbrakk> \<Longrightarrow>
s_bcorres_underlying t (whenE P f) (whenE P' f') s"
by (wpsimp simp: whenE_def|rule drop_sbcorres_underlying)+
lemma select_s_bcorres_underlying[wp]:
"A \<subseteq> B \<Longrightarrow> s_bcorres_underlying t (select A) (select B) s"
by (simp add: s_bcorres_underlying_def select_def image_def) blast
lemma fail_s_bcorres_underlying[wp]:
"s_bcorres_underlying t fail fail s"
by (simp add: s_bcorres_underlying_def fail_def)
lemma fail_bcorres_underlying[wp]:
"bcorres_underlying t fail fail"
by (simp add: bcorres_underlying_def fail_s_bcorres_underlying)
lemma assertE_bcorres_underlying[wp]:
"bcorres_underlying t (assertE P) (assertE P)"
by (wpsimp simp: assertE_def returnOk_def|rule conjI)+
lemmas assertE_s_bcorres_underlying[wp] = drop_sbcorres_underlying[OF assertE_bcorres_underlying]
lemma when_s_bcorres_underlying[wp]:
"(P \<Longrightarrow> s_bcorres_underlying t f f' s) \<Longrightarrow> s_bcorres_underlying t (when P f) (when P f') s"
by (simp add: return_s_bcorres_underlying when_def)
lemma when_bcorres_underlying[wp]:
"(P \<Longrightarrow> bcorres_underlying t f f') \<Longrightarrow> bcorres_underlying t (when P f) (when P f')"
by (simp add: bcorres_underlying_def when_s_bcorres_underlying)
lemma put_bcorres_underlying[wp]:
"t f = f' \<Longrightarrow> bcorres_underlying t (put f) (put f')"
by (simp add: bcorres_underlying_def s_bcorres_underlying_def put_def)
lemma modify_bcorres_underlying[wp]:
"(\<And>x. t (f x) = f' (t x)) \<Longrightarrow> bcorres_underlying t (modify f) (modify f')"
by (wpsimp simp: modify_def)
lemma liftM_bcorres_underlying[wp]:
"bcorres_underlying t m m' \<Longrightarrow> bcorres_underlying t (liftM f m) (liftM f m')"
by (wpsimp simp: liftM_def)
lemma sequence_x_bcorres_underlying[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow>
bcorres_underlying t (sequence_x (map f xs)) (sequence_x (map f' xs))"
by (induct xs; wpsimp simp: sequence_x_def)
lemma sequence_bcorres_underlying[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow>
bcorres_underlying t (sequence (map f xs)) (sequence (map f' xs))"
by (induct xs; wpsimp simp: sequence_def)
lemma mapM_x_bcorres_underlying[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow> bcorres_underlying t (mapM_x f xs) (mapM_x f' xs)"
by (wpsimp simp: mapM_x_def)
lemma mapM_bcorres_underlying[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow> bcorres_underlying t (mapM f xs) (mapM f' xs)"
by (simp add: mapM_def | wp)+
lemma gets_s_bcorres_underlyingE':
"s_bcorres_underlying t (f (x s)) (f' (x' (t s))) s \<Longrightarrow>
s_bcorres_underlying t (liftE (gets x) >>=E f) (liftE (gets x') >>=E f') s"
by (simp add: gets_def liftE_def lift_def bindE_def) wp
lemma bcorres_underlying_filterM[wp]:
"(\<And>x. bcorres_underlying t (a x) (a' x)) \<Longrightarrow> bcorres_underlying t (filterM a b) (filterM a' b)"
by (induct b; wpsimp simp: filterM_def)
lemma option_rec_bcorres_underlying[wp_split]:
"(\<And>x y. bcorres_underlying t (g x y) (g' x y)) \<Longrightarrow>
(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow>
bcorres_underlying t (rec_option f g a b) (rec_option f' g' a b)"
by (cases a, simp+)
lemma bcorres_underlying_mapME[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow> bcorres_underlying t (mapME f r) (mapME f' r)"
by (induct r; wpsimp simp: mapME_def sequenceE_def)
lemma handle2_bcorres_underlying[wp]:
"bcorres_underlying t f f' \<Longrightarrow>
(\<And>x. bcorres_underlying t (g x) (g' x)) \<Longrightarrow>
bcorres_underlying t (f <handle2> g) (f' <handle2> g')"
by (wpsimp simp: handleE'_def)
lemma liftME_bcorres_underlying[wp]:
"bcorres_underlying t f f' \<Longrightarrow> bcorres_underlying t (liftME a f) (liftME a f')"
by (wpsimp simp: liftME_def)
lemma zipWithM_x_bcorres[wp]:
"(\<And>x y. bcorres_underlying t (f x y) (f' x y) ) \<Longrightarrow>
bcorres_underlying t (zipWithM_x f xs ys) (zipWithM_x f' xs ys)"
by (wpsimp simp: zipWithM_x_def zipWith_def split_def)
lemma mapME_x_bcorres_underlying[wp]:
"(\<And>x. bcorres_underlying t (f x) (f' x)) \<Longrightarrow> bcorres_underlying t (mapME_x f xs) (mapME_x f' xs)"
by (induct xs; wpsimp simp: mapME_x_def sequenceE_x_def)
lemma liftE_bind_bcorres[wp]:
"bcorres_underlying t (f >>= g) (f' >>= g') \<Longrightarrow>
bcorres_underlying t (liftE f >>=E g) (liftE f' >>=E g')"
by (simp add: gets_def bcorres_underlying_def s_bcorres_underlying_def get_def bind_def return_def
split_def liftE_def bindE_def lift_def)
lemma select_f_bcorres[wp]: "bcorres_underlying t (select_f f) (select_f f)"
by (fastforce simp: select_f_def bcorres_underlying_def s_bcorres_underlying_def)
lemma bcorres_underlying_if[wp]:
"(b \<Longrightarrow> bcorres_underlying t f f') \<Longrightarrow>
(\<not>b \<Longrightarrow> bcorres_underlying t g g') \<Longrightarrow>
bcorres_underlying t (if b then f else g) (if b then f' else g')"
by (case_tac b; simp)
lemma assert_opt_bcorres_underlying[wp]:
"bcorres_underlying t (assert_opt f) (assert_opt f)"
by (wpsimp simp: assert_opt_def)
lemma unlessb_corres_underlying[wp]:
"bcorres_underlying t f f' \<Longrightarrow> bcorres_underlying t (unless a f) (unless a f')"
by (wpsimp simp: unless_def)
lemma select_bcorres_underlying[wp]:
"A \<subseteq> B \<Longrightarrow> bcorres_underlying t (select A) (select B)"
by (fastforce simp: bcorres_underlying_def select_def s_bcorres_underlying_def)
lemma catch_bcorres[wp]:
"bcorres_underlying t f f' \<Longrightarrow>
(\<And>x. bcorres_underlying t (g x) (g' x)) \<Longrightarrow>
bcorres_underlying t (f <catch> g) (f' <catch> g')"
unfolding catch_def by wpsimp
lemma whenE_bcorres_underlying[wp]:
"\<lbrakk> \<lbrakk>P = P'; P\<rbrakk> \<Longrightarrow> bcorres_underlying t f f'; P = P' \<rbrakk> \<Longrightarrow>
bcorres_underlying t (whenE P f) (whenE P' f')"
unfolding whenE_def by wpsimp
lemma unlessE_bcorres[wp]:
"bcorres_underlying t f f' \<Longrightarrow> bcorres_underlying t (unlessE P f) (unlessE P f')"
by (wpsimp simp: unlessE_def)
lemma alternative_bcorres[wp]:
"\<lbrakk> bcorres_underlying t f f'; bcorres_underlying t g g' \<rbrakk> \<Longrightarrow>
bcorres_underlying t (f \<sqinter> g) (f' \<sqinter> g')"
by (fastforce simp: alternative_def bcorres_underlying_def s_bcorres_underlying_def)
lemma gets_the_bcorres_underlying[wp]:
"(\<And>s. f' (t s) = f s) \<Longrightarrow> bcorres_underlying t (gets_the f) (gets_the f')"
by (wpsimp simp: gets_the_def)
ML \<open>
structure CrunchBCorresInstance : CrunchInstance =
struct
val name = "bcorres";
val prefix_name_scheme = false;
type extra = term;
val eq_extra = ae_conv;
fun parse_extra ctxt extra
= case extra of
"" => error "bcorres needs truncate function"
| e =>(Syntax.parse_term ctxt "%_. True", Syntax.parse_term ctxt e);
val has_preconds = false;
fun mk_term _ body extra =
(Syntax.parse_term @{context} "bcorres_underlying") $ extra $ body $ body;
fun dest_term (Const (@{const_name "bcorres_underlying"}, _) $ extra $ body $ _)
= SOME (Term.dummy, body, extra)
| dest_term _ = NONE;
fun put_precond _ ((v as Const (@{const_name "bcorres_underlying"}, _)) $ extra $ body $ body')
= v $ extra $ body $ body'
| put_precond _ _ = error "put_precond: not an bcorres term";
val pre_thms = [];
val wpc_tactic = WeakestPreCases.wp_cases_tac @{thms wpc_processors};
fun wps_tactic _ _ _ = no_tac;
val magic = Syntax.parse_term @{context}
"\<lambda>mapp_lambda_ignore. bcorres_underlying t_free_ignore mapp_lambda_ignore g_free_ignore";
val get_monad_state_type = get_nondet_monad_state_type;
end;
structure CrunchBCorres : CRUNCH = Crunch(CrunchBCorresInstance);
\<close>
setup \<open>
add_crunch_instance "bcorres" (CrunchBCorres.crunch_x, CrunchBCorres.crunch_ignore_add_dels)
\<close>
end