@@ -33,11 +33,12 @@ text \<open>
3333 for the usual Boolean connectives, but will also wish to lift an rcorres goal to a @{term valid}
3434 goal when the postcondition of the rcorres goal mentions only the return value and state from
3535 one of the two monads. These lifting rules often require @{term no_fail} assumptions, and so when
36- lifting an rcorres goal with concrete function that is a @{term Nondet_Monad.bind} of other
36+ lifting an rcorres goal with a concrete function that is a @{term Nondet_Monad.bind} of other
3737 functions, we will immediately be required to show @{term no_fail} for the composite function
3838 anyway. Therefore, we have chosen to keep failure separate. The section below regarding
3939 interactions with @{term no_fail} includes a rule that allows us to show @{term no_fail} for
40- composite functions by transforming complex predicates with rcorres.\<close>
40+ composite functions by transforming complex predicates with rcorres. The section below regarding
41+ @{term corres_underlying} shows the relation between rcorres and @{term corres_underlying}.\<close>
4142
4243definition rcorres ::
4344 "('s \<Rightarrow> 't \<Rightarrow> bool) \<Rightarrow> ('s, 'a) nondet_monad \<Rightarrow> ('t, 'b) nondet_monad
@@ -47,7 +48,7 @@ definition rcorres ::
4748 \<forall>s s'. R s s' \<longrightarrow> (\<forall>(rv', t') \<in> fst (f' s'). \<exists>(rv, t) \<in> fst (f s). R' rv rv' t t')"
4849
4950
50- chapter \<open>Interactions with @{term valid}\<close>
51+ section \<open>Interactions with @{term valid}\<close>
5152
5253lemma rcorres_as_valid :
5354 "rcorres R f f' R' \<longleftrightarrow> (\<forall>s. \<lbrace>\<lambda>s'. R s s'\<rbrace> f' \<lbrace>\<lambda>rv' t'. \<exists>(rv, t) \<in> fst (f s). R' rv rv' t t'\<rbrace>)"
@@ -73,7 +74,7 @@ lemma rcorres_from_valid_det:
7374 by ( force simp : rcorres_def det_wp_def valid_def )
7475
7576
76- chapter \<open>Manipulating the precondition and the postcondition\<close>
77+ section \<open>Manipulating the precondition and the postcondition\<close>
7778
7879lemma rcorres_weaken_pre :
7980 "\<lbrakk>rcorres Q' f f' R; \<And>s s'. Q s s' \<Longrightarrow> Q' s s'\<rbrakk> \<Longrightarrow> rcorres Q f f' R"
@@ -109,7 +110,7 @@ lemma rcorres_assume_name_pre:
109110 by ( fastforce simp : rcorres_def )
110111
111112
112- chapter \<open>Interactions with @{term Nondet_Monad.bind}\<close>
113+ section \<open>Interactions with @{term Nondet_Monad.bind}\<close>
113114
114115lemma rcorres_split :
115116 "\<lbrakk>\<And>rv rv'. rcorres (Q rv rv') (b rv) (d rv') R; rcorres P a c Q\<rbrakk>
@@ -135,7 +136,7 @@ lemma rcorres_add_return_r:
135136 by ( simp add : rcorres_def )
136137
137138
138- chapter \<open>Symbolic execution and assertions\<close>
139+ section \<open>Symbolic execution and assertions\<close>
139140
140141lemma rcorres_symb_exec_l :
141142 "\<lbrakk>\<And>s'. \<lbrace>\<lambda>s. R s s'\<rbrace> a \<lbrace>\<lambda>rv s. Q rv s s'\<rbrace>; \<And>s s'. R s s' \<Longrightarrow> \<lbrace>(=) s\<rbrace> a \<exists>\<lbrace>\<lambda>r. (=) s\<rbrace>;
@@ -287,7 +288,7 @@ lemma rcorres_split_gets_the_fwd:
287288 by ( fastforce intro : rcorres_weaken_pre [ OF rcorres_split_gets_the ])
288289
289290
290- chapter \<open>if\<close>
291+ section \<open>if\<close>
291292
292293lemma rcorres_if_l :
293294 "\<lbrakk>b \<Longrightarrow> rcorres T f f' R'; \<not> b \<Longrightarrow> rcorres F g f' R'\<rbrakk>
@@ -304,7 +305,7 @@ lemma rcorres_if_r:
304305lemmas rcorres_if_r_fwd = rcorres_if_r [ where T = R and F = R for R , simplified ]
305306
306307
307- chapter \<open>Lifting rules\<close>
308+ section \<open>Lifting rules\<close>
308309
309310text \<open>
310311 We would like a lifting rule for conjunctions, and so a rule with assumptions including
@@ -326,9 +327,8 @@ text \<open>
326327 assumption does allow us to make this inference, and so we include this assumption in our rule.
327328
328329 It does not seem possible for us to state an adequate lifting rule for conjunction for
329- @{term rcorres}, and so for an abstract monadic function that is not deterministic,
330- it may be necessary to unfold the definition of @{term rcorres} in order to show a postcondition
331- that is a conjunction.\<close>
330+ @{term rcorres} with a nondeterministic abstract monadic function, and so in such a situation,
331+ it may be necessary to unfold the definition of @{term rcorres}.\<close>
332332lemma rcorres_conj_lift :
333333 "\<lbrakk>\<And>s'. det_wp (\<lambda>s. P s s') f; rcorres Q f f' R'; rcorres R f f' Q'\<rbrakk>
334334 \<Longrightarrow> rcorres
@@ -417,7 +417,7 @@ lemma rcorres_lift_conc_only:
417417lemmas rcorres_lift_conc_only_fwd = rcorres_lift_conc_only [ where P = P and R = P for P , simplified ]
418418
419419
420- chapter \<open>Interactions with @{term corres_underlying}\<close>
420+ section \<open>Interactions with @{term corres_underlying}\<close>
421421
422422lemma corres_underlying_from_rcorres :
423423 "\<lbrakk>nf' \<Longrightarrow> no_fail (\<lambda>s'. \<exists>s. (s, s') \<in> srel \<and> P s \<and> P' s') f';
@@ -431,7 +431,7 @@ lemma rcorres_from_corres_underlying:
431431 by ( fastforce simp : corres_underlying_def rcorres_def no_fail_def )
432432
433433
434- chapter \<open>Interactions with @{term no_fail}\<close>
434+ section \<open>Interactions with @{term no_fail}\<close>
435435
436436lemma no_fail_rcorres_bind :
437437 "\<lbrakk>\<And>rv rv'. no_fail (\<lambda>s'. \<exists>s. R rv rv' s s') (g' rv'); rcorres Q f f' R;
@@ -444,23 +444,24 @@ lemma no_fail_rcorres_bind:
444444 done
445445
446446
447- chapter \<open>Automation\<close>
447+ section \<open>Automation\<close>
448448
449449named_theorems rcorres
450450named_theorems rcorres_lift
451451
452- method rcorres_step uses rcorres_del wp simp declares rcorres rcorres_lift =
453- declaring rcorres_del [ rcorres del ] in
452+ method rcorres_step uses rcorres_del rcorres_lift_del wp simp declares rcorres rcorres_lift =
453+ declaring rcorres_del [ rcorres del ] rcorres_lift_del [ rcorres_lift del ] in
454454 \<open>rule rcorres
455455 | rule rcorres_split rcorres_conj_lift
456456 | rule rcorres_lift rcorres_lift_abs_only rcorres_lift_conc_only
457457 | wpsimp wp: wp simp: simp\<close>
458458
459459declare rcorres_weaken_pre [ wp_pre ]
460460
461- method rcorres uses rcorres_del wp simp declares rcorres rcorres_lift =
461+ method rcorres uses rcorres_del rcorres_lift_del wp simp declares rcorres rcorres_lift =
462462 wp_pre ,
463- (( rcorres_step rcorres : rcorres rcorres_del : rcorres_del rcorres_lift : rcorres_lift
463+ (( rcorres_step rcorres : rcorres rcorres_del : rcorres_del
464+ rcorres_lift : rcorres_lift rcorres_lift_del : rcorres_lift_del
464465 wp : wp simp : simp )+)[ 1 ]
465466
466467text \<open>
@@ -473,4 +474,63 @@ method rcorres_conj_lift methods solve uses rule simp wp =
473474 ( rule rcorres_lift , ( solves \<open>rule rule\<close> | solves \<open>wpsimp wp: wp simp: simp\<close> )+)[ 1 ],
474475 solves solve
475476
477+ experiment
478+ fixes f f' :: "('s, 'r) nondet_monad"
479+ fixes g g' h :: "'r \<Rightarrow> ('s, 'r) nondet_monad"
480+
481+ fixes P Q :: "'s \<Rightarrow> bool"
482+ fixes R V :: "'s \<Rightarrow> 's \<Rightarrow> bool"
483+ fixes S T U :: "'r \<Rightarrow> 'r \<Rightarrow> 's \<Rightarrow> 's \<Rightarrow> bool"
484+
485+ assumes [ wp ]: "f \<lbrace>P\<rbrace>" "\<And>rv. g rv \<lbrace>P\<rbrace>" "f \<lbrace>Q\<rbrace>" "\<And>rv. g rv \<lbrace>Q\<rbrace>"
486+ assumes [ wp ]: "no_fail P f" "\<And>rv. no_fail P (g rv)"
487+ assumes [ wp ]: "det_wp P f"
488+ assumes [ wp ]: "empty_fail f" "\<And>rv. empty_fail (g rv)"
489+
490+ assumes [ rcorres ]: "rcorres R f f' S"
491+ assumes [ rcorres ]: "\<And>rv rv'. rcorres (S rv rv') (g rv) (g' rv') T"
492+ assumes [ rcorres ]: "\<And>rv rv'. rcorres (T rv rv') (h rv) (return rv') U"
493+
494+ assumes
495+ lift [ rcorres_lift ]:
496+ "\<And>(f :: ('s, 'r) nondet_monad) (f' :: ('s, 'r) nondet_monad).
497+ \<lbrakk>no_fail P f; empty_fail f; f \<lbrace>Q\<rbrace>\<rbrakk> \<Longrightarrow> rcorres V f f' (\<lambda>_ _. V)"
498+ begin
499+
500+ text \<open>The rcorres method works very similarly to wpsimp in straightforward cases.\<close>
501+ lemma "rcorres R (do rv \<leftarrow> f; g rv od) (do rv \<leftarrow> f'; g' rv od) T"
502+ apply rcorres
503+ by simp
504+
505+ text \<open>
506+ It may help to add a @{term return} on one side in order to balance the abstract and concrete
507+ functions, so that splitting occurs in the desired way.\<close>
508+ lemma "rcorres R (do x \<leftarrow> f; y \<leftarrow> g x; h y od) (do x \<leftarrow> f'; g' x od) U"
509+ apply ( rule rcorres_add_return_r )
510+ apply ( simp only : bind_assoc ) \<comment> \<open>now @{term h} will be lined up with @{term return}\<close>
511+ apply rcorres
512+ by simp
513+
514+ text \<open>
515+ Although the rule @{thm lift} is in the set rcorres_lift, in this instance, we can give the rule
516+ directly to the rcorres argument for it to be applied before the method attempts to split the
517+ functions.\<close>
518+ lemma "rcorres V (do rv \<leftarrow> f; g rv od) (do rv \<leftarrow> f'; g' rv od) (\<lambda>_ _. V)"
519+ apply ( rcorres rcorres : lift )
520+ by simp
521+
522+ text
523+ \<open>When the postcondition refers to the return value and state from only one of the monads, then
524+ the rules @{thm rcorres_lift_abs_only} or @{thm rcorres_lift_conc_only} will be applied.\<close>
525+ lemma "rcorres (\<lambda>s _. P s) f f' (\<lambda>_ _ s _. P s)"
526+ apply rcorres
527+ by simp
528+
529+ text \<open>A typical example of the rcorres_conj_lift method.\<close>
530+ lemma "rcorres (\<lambda>s s'. V s s' \<and> P s) f f' (\<lambda>_ _ s s'. V s s' \<and> W s s')"
531+ apply ( rcorres_conj_lift \<open>clarsimp\<close> ) \<comment> \<open>breaks off the first conjunct and solves it with @{thm lift}\<close>
532+ oops \<comment> \<open>leaves the goal with the same precondition, and the second conjunct as the postcondition\<close>
533+
534+ end
535+
476536end
0 commit comments