(* Title: GPV_Bisim.thy
Author: Andreas Lochbihler, ETH Zurich *)
theory GPV_Bisim imports
GPV_Expectation begin
subsection‹Bisimulation for oracles›
text‹Bisimulation is a consequence of parametricity›
lemma exec_gpv_oracle_bisim': assumes *: "X s1 s2" and bisim: "∧s1 s2 x. X s1 s2 ==> rel_spmf (λ(a, s1') (b, s2'). a = b ∧ X s1' s2') (oracle1 s1 x) (oracle2 s2 x)" shows"rel_spmf (λ(a, s1') (b, s2'). a = b ∧ X s1' s2') (exec_gpv oracle1 gpv s1) (exec_gpv oracle2 gpv s2)" by(rule exec_gpv_parametric[of X "(=)""(=)", unfolded gpv.rel_eq rel_prod_conv, THEN rel_funD, THEN rel_funD, THEN rel_funD, OF rel_funI refl, OF rel_funI *])(simp add: bisim)
lemma exec_gpv_oracle_bisim: assumes *: "X s1 s2" and bisim: "∧s1 s2 x. X s1 s2 ==> rel_spmf (λ(a, s1') (b, s2'). a = b ∧ X s1' s2') (oracle1 s1 x) (oracle2 s2 x)" and R: "∧x s1' s2'. [ X s1' s2'; (x, s1') ∈ set_spmf (exec_gpv oracle1 gpv s1); (x, s2') ∈ set_spmf (exec_gpv oracle2 gpv s2) ]==> R (x, s1') (x, s2')" shows"rel_spmf R (exec_gpv oracle1 gpv s1) (exec_gpv oracle2 gpv s2)" apply(rule spmf_rel_mono_strong) apply(rule exec_gpv_oracle_bisim'[OF * bisim]) apply(auto dest: R) done
lemma run_gpv_oracle_bisim: assumes"X s1 s2" and"∧s1 s2 x. X s1 s2 ==> rel_spmf (λ(a, s1') (b, s2'). a = b ∧ X s1' s2') (oracle1 s1 x) (oracle2 s2 x)" shows"run_gpv oracle1 gpv s1 = run_gpv oracle2 gpv s2" using exec_gpv_oracle_bisim'[OF assms] by(fold spmf_rel_eq)(fastforce simp add: spmf_rel_map intro: rel_spmf_mono)
context fixes joint_oracle :: "('s1 × 's2) → 'a → (('b × 's1) × ('b × 's2)) spmf" and oracle1 :: "'s1 → 'a → ('b × 's1) spmf" and bad1 :: "'s1 → bool" and oracle2 :: "'s2 → 'a → ('b × 's2) spmf" and bad2 :: "'s2 → bool" begin
partial_function (spmf) exec_until_bad :: "('x, 'a, 'b) gpv → 's1 → 's2 → (('x × 's1) × ('x × 's2)) spmf"
where "exec_until_bad gpv s1 s2 = (if bad1 s1 ∨ bad2 s2 then pair_spmf (exec_gpv oracle1 gpv s1) (exec_gpv oracle2 gpv s2) else bind_spmf (the_gpv gpv) (λgenerat. case generat of Pure x → return_spmf ((x, s1), (x, s2)) | IO out f → bind_spmf (joint_oracle (s1, s2) out) (λ((x, s1'), (y, s2')). if bad1 s1' ∨ bad2 s2' then pair_spmf (exec_gpv oracle1 (f x) s1') (exec_gpv oracle2 (f y) s2') else exec_until_bad (f x) s1' s2')))"
lemma exec_until_bad_fixp_induct [case_names adm bottom step]: assumes"ccpo.admissible (fun_lub lub_spmf) (fun_ord (ord_spmf (=))) (λf. P (λgpv s1 s2. f ((gpv, s1), s2)))" and"P (λ_ _ _. return_pmf None)" and"∧exec_until_bad'. P exec_until_bad' ==> P (λgpv s1 s2. if bad1 s1 ∨ bad2 s2 then pair_spmf (exec_gpv oracle1 gpv s1) (exec_gpv oracle2 gpv s2) else bind_spmf (the_gpv gpv) (λgenerat. case generat of Pure x → return_spmf ((x, s1), (x, s2)) | IO out f → bind_spmf (joint_oracle (s1, s2) out) (λ((x, s1'), (y, s2')). if bad1 s1' ∨ bad2 s2' then pair_spmf (exec_gpv oracle1 (f x) s1') (exec_gpv oracle2 (f y) s2') else exec_until_bad' (f x) s1' s2')))" shows"P exec_until_bad" using assms by(rule exec_until_bad.fixp_induct[unfolded curry_conv[abs_def]])
end
lemma exec_gpv_oracle_bisim_bad_plossless: fixes s1 :: 's1 and s2 :: 's2 and X :: "'s1 → 's2 → bool" and oracle1 :: "'s1 → 'a → ('b × 's1) spmf" and oracle2 :: "'s2 → 'a → ('b × 's2) spmf" assumes *: "if bad2 s2 then X_bad s1 s2 else X s1 s2" and bad: "bad1 s1 = bad2 s2" and bisim: "∧s1 s2 x. [ X s1 s2; x ∈ outs_II]==> rel_spmf (λ(a, s1') (b, s2'). bad1 s1' = bad2 s2' ∧ (if bad2 s2' then X_bad s1' s2' else a = b ∧ X s1' s2')) (oracle1 s1 x) (oracle2 s2 x)" and bad_sticky1: "∧s2. bad2 s2 ==> callee_invariant_on oracle1 (λs1. bad1 s1 ∧ X_bad s1 s2) I" and bad_sticky2: "∧s1. bad1 s1 ==> callee_invariant_on oracle2 (λs2. bad2 s2 ∧ X_bad s1 s2) I" and lossless1: "∧s1 x. [ bad1 s1; x ∈ outs_II]==> lossless_spmf (oracle1 s1 x)" and lossless2: "∧s2 x. [ bad2 s2; x ∈ outs_II]==> lossless_spmf (oracle2 s2 x)" and lossless: "plossless_gpv I gpv" and WT_oracle1: "∧s1. I⊨c oracle1 s1 √"(* stronger than the invariants above because unconditional *) and WT_oracle2: "∧s2. I⊨c oracle2 s2 √" and WT_gpv: "I⊨g gpv √" shows"rel_spmf (λ(a, s1') (b, s2'). bad1 s1' = bad2 s2' ∧ (if bad2 s2' then X_bad s1' s2' else a = b ∧ X s1' s2')) (exec_gpv oracle1 gpv s1) (exec_gpv oracle2 gpv s2)"
(is"rel_spmf ?R ?p ?q") proof - let ?R' = "λ(a, s1') (b, s2'). bad1 s1' = bad2 s2' ∧ (if bad2 s2' then X_bad s1' s2' else a = b ∧ X s1' s2')" from bisim have"∀s1 s2. ∀x ∈ outs_II. X s1 s2 ⟶ rel_spmf ?R' (oracle1 s1 x) (oracle2 s2 x)"by blast thenobtain joint_oracle
where oracle1 [symmetric]: "∧s1 s2 x. [ X s1 s2; x ∈ outs_II]==> map_spmf fst (joint_oracle s1 s2 x) = oracle1 s1 x" and oracle2 [symmetric]: "∧s1 s2 x. [ X s1 s2; x ∈ outs_II]==> map_spmf snd (joint_oracle s1 s2 x) = oracle2 s2 x" and3 [rotated 2]: "∧s1 s2 x y y' s1' s2'. [ X s1 s2; x ∈ outs_II; ((y, s1'), (y', s2')) ∈ set_spmf (joint_oracle s1 s2 x) ] ==> bad1 s1' = bad2 s2' ∧ (if bad2 s2' then X_bad s1' s2' else y = y' ∧ X s1' s2')" apply atomize_elim apply(unfold rel_spmf_simps all_conj_distrib[symmetric] all_simps(6) imp_conjR[symmetric]) apply(subst choice_iff[symmetric] ex_simps(6))+ apply fastforce done let ?joint_oracle = "λ(s1, s2). joint_oracle s1 s2" let ?pq = "exec_until_bad ?joint_oracle oracle1 bad1 oracle2 bad2 gpv s1 s2"
have setD: "∧s1 s2 x y y' s1' s2'. [ X s1 s2; x ∈ outs_II; ((y, s1'), (y', s2')) ∈ set_spmf (joint_oracle s1 s2 x) ] ==> (y, s1') ∈ set_spmf (oracle1 s1 x) ∧ (y', s2') ∈ set_spmf (oracle2 s2 x)" unfolding oracle1 oracle2 by(auto intro: rev_image_eqI) show ?thesis proof show"map_spmf fst ?pq = exec_gpv oracle1 gpv s1" proof(rule spmf.leq_antisym) show"ord_spmf (=) (map_spmf fst ?pq) (exec_gpv oracle1 gpv s1)"using * bad WT_gpv lossless proof(induction arbitrary: s1 s2 gpv rule: exec_until_bad_fixp_induct) case adm show ?caseby simp case bottom show ?caseby simp case (step exec_until_bad') show ?case proof(cases "bad2 s2") case True thenhave"weight_spmf (exec_gpv oracle2 gpv s2) = 1" using callee_invariant_on.weight_exec_gpv[OF bad_sticky2 lossless2, of s1 gpv s2]
step.prems weight_spmf_le_1[of "exec_gpv oracle2 gpv s2"] by(simp add: pgen_lossless_gpv_def weight_gpv_def) thenshow ?thesis using True by simp next case False hence"¬ bad1 s1"using step.prems(2) by simp moreover { fix out c r1 s1' r2 s2' assume IO: "IO out c ∈ set_spmf (the_gpv gpv)" and joint: "((r1, s1'), (r2, s2')) ∈ set_spmf (joint_oracle s1 s2 out)" from step.prems(3) IO have out: "out ∈ outs_II"by(rule WT_gpvD) from setD[OF _ out joint] step.prems(1) False have1: "(r1, s1') ∈ set_spmf (oracle1 s1 out)" and2: "(r2, s2') ∈ set_spmf (oracle2 s2 out)"by simp_all hence r1: "r1 ∈ responses_II out"and r2: "r2 ∈ responses_II out" using WT_oracle1 WT_oracle2 out by(blast dest: WT_calleeD)+ have *: "plossless_gpv I (c r2)"using step.prems(4) IO r2 step.prems(3) by(rule plossless_gpv_ContD) thenhave"bad2 s2' ==> weight_spmf (exec_gpv oracle2 (c r2) s2') = 1" and"¬ bad2 s2' ==> ord_spmf (=) (map_spmf fst (exec_until_bad' (c r2) s1' s2')) (exec_gpv oracle1 (c r2) s1')" using callee_invariant_on.weight_exec_gpv[OF bad_sticky2 lossless2, of s1' "c r2" s2']
weight_spmf_le_1[of "exec_gpv oracle2 (c r2) s2'"] WT_gpv_ContD[OF step.prems(3) IO r2] 3[OF joint _ out] step.prems(1) False by(simp_all add: pgen_lossless_gpv_def weight_gpv_def step.IH) } ultimatelyshow ?thesis using False step.prems(1) by(rewrite in"ord_spmf _ _ 🚫" exec_gpv.simps)
(fastforce simp add: split_def bind_map_spmf map_spmf_bind_spmf oracle1 WT_gpv_OutD[OF step.prems(3)] intro!: ord_spmf_bind_reflI split!: generat.split dest: 3) qed qed show"ord_spmf (=) (exec_gpv oracle1 gpv s1) (map_spmf fst ?pq)"using * bad WT_gpv lossless proof(induction arbitrary: gpv s1 s2 rule: exec_gpv_fixp_induct_strong) case adm show ?caseby simp case bottom show ?caseby simp case (step exec_gpv') thenshow ?case proof(cases "bad2 s2") case True thenhave"weight_spmf (exec_gpv oracle2 gpv s2) = 1" using callee_invariant_on.weight_exec_gpv[OF bad_sticky2 lossless2, of s1 gpv s2]
step.prems weight_spmf_le_1[of "exec_gpv oracle2 gpv s2"] by(simp add: pgen_lossless_gpv_def weight_gpv_def) thenshow ?thesis using True by(rewrite exec_until_bad.simps; rewrite exec_gpv.simps)
(clarsimp intro!: ord_spmf_bind_reflI split!: generat.split simp add: step.hyps) next case False hence"¬ bad1 s1"using step.prems(2) by simp moreover { fix out c r1 s1' r2 s2' assume IO: "IO out c ∈ set_spmf (the_gpv gpv)" and joint: "((r1, s1'), (r2, s2')) ∈ set_spmf (joint_oracle s1 s2 out)" from step.prems(3) IO have out: "out ∈ outs_II"by(rule WT_gpvD) from setD[OF _ out joint] step.prems(1) False have1: "(r1, s1') ∈ set_spmf (oracle1 s1 out)" and2: "(r2, s2') ∈ set_spmf (oracle2 s2 out)"by simp_all hence r1: "r1 ∈ responses_II out"and r2: "r2 ∈ responses_II out" using WT_oracle1 WT_oracle2 out by(blast dest: WT_calleeD)+ have *: "plossless_gpv I (c r2)"using step.prems(4) IO r2 step.prems(3) by(rule plossless_gpv_ContD) thenhave"bad2 s2' ==> weight_spmf (exec_gpv oracle2 (c r2) s2') = 1" and"¬ bad2 s2' ==> ord_spmf (=) (exec_gpv' (c r2) s1') (map_spmf fst (exec_until_bad (λ(x, y). joint_oracle x y) oracle1 bad1 oracle2 bad2 (c r2) s1' s2'))" using callee_invariant_on.weight_exec_gpv[OF bad_sticky2 lossless2, of s1' "c r2" s2']
weight_spmf_le_1[of "exec_gpv oracle2 (c r2) s2'"] WT_gpv_ContD[OF step.prems(3) IO r2] 3[OF joint _ out] step.prems(1) False by(simp_all add: pgen_lossless_gpv_def weight_gpv_def step.IH) } ultimatelyshow ?thesis using False step.prems(1) by(rewrite exec_until_bad.simps)
(fastforce simp add: map_spmf_bind_spmf WT_gpv_OutD[OF step.prems(3)] oracle1 bind_map_spmf step.hyps intro!: ord_spmf_bind_reflI split!: generat.split dest: 3) qed qed qed
show"map_spmf snd ?pq = exec_gpv oracle2 gpv s2" proof(rule spmf.leq_antisym) show"ord_spmf (=) (map_spmf snd ?pq) (exec_gpv oracle2 gpv s2)"using * bad WT_gpv lossless proof(induction arbitrary: s1 s2 gpv rule: exec_until_bad_fixp_induct) case adm show ?caseby simp case bottom show ?caseby simp case (step exec_until_bad') show ?case proof(cases "bad2 s2") case True thenhave"weight_spmf (exec_gpv oracle1 gpv s1) = 1" using callee_invariant_on.weight_exec_gpv[OF bad_sticky1 lossless1, of s2 gpv s1]
step.prems weight_spmf_le_1[of "exec_gpv oracle1 gpv s1"] by(simp add: pgen_lossless_gpv_def weight_gpv_def) thenshow ?thesis using True by simp next case False hence"¬ bad1 s1"using step.prems(2) by simp moreover { fix out c r1 s1' r2 s2' assume IO: "IO out c ∈ set_spmf (the_gpv gpv)" and joint: "((r1, s1'), (r2, s2')) ∈ set_spmf (joint_oracle s1 s2 out)" from step.prems(3) IO have out: "out ∈ outs_II"by(rule WT_gpvD) from setD[OF _ out joint] step.prems(1) False have1: "(r1, s1') ∈ set_spmf (oracle1 s1 out)" and2: "(r2, s2') ∈ set_spmf (oracle2 s2 out)"by simp_all hence r1: "r1 ∈ responses_II out"and r2: "r2 ∈ responses_II out" using WT_oracle1 WT_oracle2 out by(blast dest: WT_calleeD)+ have *: "plossless_gpv I (c r1)"using step.prems(4) IO r1 step.prems(3) by(rule plossless_gpv_ContD) thenhave"bad2 s2' ==> weight_spmf (exec_gpv oracle1 (c r1) s1') = 1" and"¬ bad2 s2' ==> ord_spmf (=) (map_spmf snd (exec_until_bad' (c r2) s1' s2')) (exec_gpv oracle2 (c r2) s2')" using callee_invariant_on.weight_exec_gpv[OF bad_sticky1 lossless1, of s2' "c r1" s1']
weight_spmf_le_1[of "exec_gpv oracle1 (c r1) s1'"] WT_gpv_ContD[OF step.prems(3) IO r1] 3[OF joint _ out] step.prems(1) False by(simp_all add: pgen_lossless_gpv_def weight_gpv_def step.IH) } ultimatelyshow ?thesis using False step.prems(1) by(rewrite in"ord_spmf _ _ 🚫" exec_gpv.simps)
(fastforce simp add: split_def bind_map_spmf map_spmf_bind_spmf oracle2 WT_gpv_OutD[OF step.prems(3)] intro!: ord_spmf_bind_reflI split!: generat.split dest: 3) qed qed show"ord_spmf (=) (exec_gpv oracle2 gpv s2) (map_spmf snd ?pq)"using * bad WT_gpv lossless proof(induction arbitrary: gpv s1 s2 rule: exec_gpv_fixp_induct_strong) case adm show ?caseby simp case bottom show ?caseby simp case (step exec_gpv') thenshow ?case proof(cases "bad2 s2") case True thenhave"weight_spmf (exec_gpv oracle1 gpv s1) = 1" using callee_invariant_on.weight_exec_gpv[OF bad_sticky1 lossless1, of s2 gpv s1]
step.prems weight_spmf_le_1[of "exec_gpv oracle1 gpv s1"] by(simp add: pgen_lossless_gpv_def weight_gpv_def) thenshow ?thesis using True by(rewrite exec_until_bad.simps; subst (2) exec_gpv.simps)
(clarsimp intro!: ord_spmf_bind_reflI split!: generat.split simp add: step.hyps) next case False hence"¬ bad1 s1"using step.prems(2) by simp moreover { fix out c r1 s1' r2 s2' assume IO: "IO out c ∈ set_spmf (the_gpv gpv)" and joint: "((r1, s1'), (r2, s2')) ∈ set_spmf (joint_oracle s1 s2 out)" from step.prems(3) IO have out: "out ∈ outs_II"by(rule WT_gpvD) from setD[OF _ out joint] step.prems(1) False have1: "(r1, s1') ∈ set_spmf (oracle1 s1 out)" and2: "(r2, s2') ∈ set_spmf (oracle2 s2 out)"by simp_all hence r1: "r1 ∈ responses_II out"and r2: "r2 ∈ responses_II out" using WT_oracle1 WT_oracle2 out by(blast dest: WT_calleeD)+ have *: "plossless_gpv I (c r1)"using step.prems(4) IO r1 step.prems(3) by(rule plossless_gpv_ContD) thenhave"bad2 s2' ==> weight_spmf (exec_gpv oracle1 (c r1) s1') = 1" and"¬ bad2 s2' ==> ord_spmf (=) (exec_gpv' (c r2) s2') (map_spmf snd (exec_until_bad (λ(x, y). joint_oracle x y) oracle1 bad1 oracle2 bad2 (c r2) s1' s2'))" using callee_invariant_on.weight_exec_gpv[OF bad_sticky1 lossless1, of s2' "c r1" s1']
weight_spmf_le_1[of "exec_gpv oracle1 (c r1) s1'"] WT_gpv_ContD[OF step.prems(3) IO r1] 3[OF joint _ out] step.prems(1) False by(simp_all add: pgen_lossless_gpv_def step.IH weight_gpv_def) } ultimatelyshow ?thesis using False step.prems(1) by(rewrite exec_until_bad.simps)
(fastforce simp add: map_spmf_bind_spmf WT_gpv_OutD[OF step.prems(3)] oracle2 bind_map_spmf step.hyps intro!: ord_spmf_bind_reflI split!: generat.split dest: 3) qed qed qed
have"set_spmf ?pq ⊆ {(as1, bs2). ?R' as1 bs2}"using * bad WT_gpv proof(induction arbitrary: gpv s1 s2 rule: exec_until_bad_fixp_induct) case adm show ?caseby(intro cont_intro ccpo_class.admissible_leI) case bottom show ?caseby simp case step have switch: "set_spmf (exec_gpv oracle1 (c r1) s1') × set_spmf (exec_gpv oracle2 (c r2) s2') ⊆ {((a, s1'), b, s2'). bad1 s1' = bad2 s2' ∧ (if bad2 s2' then X_bad s1' s2' else a = b ∧ X s1' s2')}" if"¬ bad1 s1""I⊨g gpv √""¬ bad2 s2"and X: "X s1 s2"and out: "IO out c ∈ set_spmf (the_gpv gpv)" and joint: "((r1, s1'), (r2, s2')) ∈ set_spmf (joint_oracle s1 s2 out)" and bad2: "bad2 s2'" for out c r1 s1' r2 s2' proof(clarify; rule conjI) from step.prems(3) out have outs: "out ∈ outs_II"by(rule WT_gpv_OutD) from bad2 3[OF joint X this] have bad1: "bad1 s1' ∧ X_bad s1' s2'"by simp_all
have s1': "(r1, s1') ∈ set_spmf (oracle1 s1 out)"and s2': "(r2, s2') ∈ set_spmf (oracle2 s2 out)" using setD[OF X outs joint] by simp_all have resp: "r1 ∈ responses_II out"using WT_oracle1 s1' outs by(rule WT_calleeD) with step.prems(3) out have WT1: "I⊨g c r1 √"by(rule WT_gpv_ContD) have resp: "r2 ∈ responses_II out"using WT_oracle2 s2' outs by(rule WT_calleeD) with step.prems(3) out have WT2: "I⊨g c r2 √"by(rule WT_gpv_ContD)
lemma gpv_stop_parametric': notes [transfer_rule] = the_gpv_parametric' the_gpv_parametric' Done_parametric' corec_gpv_parametric' shows"(rel_gpv'' A C R ===> rel_gpv'' (rel_option A) C (rel_option R)) gpv_stop gpv_stop" unfolding gpv_stop_def by transfer_prover
lemma gpv_stop_parametric [transfer_rule]: shows"(rel_gpv A C ===> rel_gpv (rel_option A) C) gpv_stop gpv_stop" unfolding gpv_stop_def by transfer_prover
lemma gpv_stop_transfer: "(rel_gpv'' A B C ===> rel_gpv'' (pcr_Some A) B (pcr_Some C)) (λx. x) gpv_stop" apply(rule rel_funI) subgoalfor gpv gpv' apply(coinduction arbitrary: gpv gpv') apply(drule rel_gpv''D) apply(auto simp add: spmf_rel_map generat.rel_map rel_fun_def elim!: pcr_SomeE generat.rel_mono_strong rel_spmf_mono) done done
end
lemma gpv_stop_map' [simp]: "gpv_stop (map_gpv' f g h gpv) = map_gpv' (map_option f) g (map_option h) (gpv_stop gpv)" apply(coinduction arbitrary: gpv rule: gpv.coinduct_strong) apply(auto 43 simp add: spmf_rel_map generat.rel_map intro!: rel_spmf_reflI generat.rel_refl_strong split!: option.split) done
lemma interaction_bound_gpv_stop [simp]: "interaction_bound consider (gpv_stop gpv) = interaction_bound consider gpv" proof(induction arbitrary: gpv rule: parallel_fixp_induct_strong_1_1[OF complete_lattice_partial_function_definitions complete_lattice_partial_function_definitions interaction_bound.mono interaction_bound.mono interaction_bound_def interaction_bound_def, case_names adm bottom step]) case adm show ?caseby simp case bottom show ?caseby simp next case (step interaction_bound' interaction_bound'') have"(SUP x. interaction_bound' (case x of None → Done None | Some input → gpv_stop (c input))) = (SUP input. interaction_bound'' (c input))" (is"?lhs = ?rhs"is"(SUP x. ?f x) = _") if"IO out c ∈ set_spmf (the_gpv gpv)"for out c proof - have"?lhs = sup (interaction_bound' (Done None)) (⊔x. ?f (Some x))" by (simp add: UNIV_option_conv image_comp) alsohave"interaction_bound' (Done None) = 0"using step.hyps(1)[of "Done None"] by simp alsohave"(⊔x. ?f (Some x)) = ?rhs"by (simp add: step.IH) finallyshow ?thesis by (simp add: bot_enat_def [symmetric]) qed thenshow ?case by (auto simp add: case_map_generat o_def image_comp cong del: generat.case_cong_weak if_weak_cong intro!: SUP_cong split: generat.split) qed
partial_function (spmf) exec_until_stop :: "('a option, 'c, 'r) gpv → 's1 → 's2 → bool → ('a option × 's1 × 's2) spmf"
where "exec_until_stop gpv s1 s2 b = (if b then bind_spmf (the_gpv gpv) (λgenerat. case generat of Pure x → return_spmf (x, s1, s2) | IO out rpv → bind_pmf (joint_oracle s1 s2 out) (λ(a, b). case a of None → return_pmf None | Some (r1, s1') → (case b of None → undefined | Some (r2, s2') → (case (r1, r2) of (None, None) → exec_until_stop (Done None) s1' s2' True | (Some r1', Some r2') → exec_until_stop (rpv r1') s1' s2' True | (None, Some r2') → exec_until_stop (Done None) s1' s2' True | (Some r1', None) → exec_until_stop (rpv r1') s1' s2' False)))) else bind_spmf (the_gpv gpv) (λgenerat. case generat of Pure x → return_spmf (None, s1, s2) | IO out rpv → bind_spmf (callee1 s1 out) (λ(r1, s1'). case r1 of None → exec_until_stop (Done None) s1' s2 False | Some r1' → exec_until_stop (rpv r1') s1' s2 False)))"
end
lemma ord_spmf_exec_gpv_stop: (* TODO: generalize ord_spmf to support different type variables *) fixes callee1 :: "('c, 'r option, 's) callee" and callee2 :: "('c, 'r option, 's) callee" and S :: "'s → 's → bool" and gpv :: "('a, 'c, 'r) gpv" assumes bisim: "∧s1 s2 x. [ S s1 s2; ¬ stop s2 ]==> ord_spmf (λ(r1, s1') (r2, s2'). le_option r2 r1 ∧ S s1' s2' ∧ (r2 = None ∧ r1 ≠ None ⟷ stop s2')) (callee1 s1 x) (callee2 s2 x)" and init: "S s1 s2" and go: "¬ stop s2" and sticking: "∧s1 s2 x y s1'. [ (y, s1') ∈ set_spmf (callee1 s1 x); S s1 s2; stop s2 ]==> S s1' s2" shows"ord_spmf (rel_prod (ord_option ⊤)-1-1 S) (exec_gpv_stop callee1 gpv s1) (exec_gpv_stop callee2 gpv s2)" proof - let ?R = "λ(r1, s1') (r2, s2'). le_option r2 r1 ∧ S s1' s2' ∧ (r2 = None ∧ r1 ≠ None⟷ stop s2')" obtain joint :: "'s → 's → 'c → (('r option × 's) option × ('r option × 's) option) pmf"
where j1: "map_pmf fst (joint s1 s2 x) = callee1 s1 x" and j2: "map_pmf snd (joint s1 s2 x) = callee2 s2 x" and rel [rule_format, rotated -1]: "∀(a, b) ∈ set_pmf (joint s1 s2 x). ord_option ?R a b" if"S s1 s2""¬ stop s2"for x s1 s2 using bisim apply atomize_elim apply(subst (asm) rel_pmf.simps) apply(unfold rel_spmf_simps all_conj_distrib[symmetric] all_simps(6) imp_conjR[symmetric]) apply(subst all_comm) apply(subst (2) all_comm) apply(subst choice_iff[symmetric] ex_simps(6))+ apply fastforce done note [simp del] = top_apply conversep_iff id_apply have"¬ stop s2 ==> rel_spmf (rel_prod (ord_option ⊤)-1-1 S) (exec_gpv_stop callee1 gpv s1) (map_spmf (λ(x, s1, s2). (x, s2)) (exec_until_stop joint callee1 (map_gpv Some id gpv) s1 s2 True))" and"rel_spmf (rel_prod (ord_option ⊤)-1-1 S) (exec_gpv callee1 (Done None :: ('a option, 'c, 'r option) gpv) s1) (map_spmf (λ(x, s1, s2). (x, s2)) (exec_until_stop joint callee1 (Done None :: ('a option, 'c, 'r) gpv) s1 s2 b))" and"stop s2 ==> rel_spmf (rel_prod (ord_option ⊤)-1-1 S) (exec_gpv_stop callee1 gpv s1) (map_spmf (λ(x, s1, y). (x, y)) (exec_until_stop joint callee1 (map_gpv Some id gpv) s1 s2 False))" for b using init proof(induction arbitrary: gpv s1 s2 b rule: parallel_fixp_induct_2_4[OF partial_function_definitions_spmf partial_function_definitions_spmf exec_gpv.mono exec_until_stop.mono exec_gpv_def exec_until_stop_def, unfolded lub_spmf_empty, case_names adm bottom step]) case adm show ?caseby simp
{ case bottom case1show ?caseby simp }
{ case bottom case2show ?caseby simp }
{ case bottom case3show ?caseby simp } next case (step exec_gpv' exec_until_stop') case step: 1 show ?caseusing step.prems apply(rewrite gpv_stop.sel) apply(simp add: map_spmf_bind_spmf bind_map_spmf gpv.map_sel) apply(rule rel_spmf_bind_reflI) apply(clarsimp split!: generat.split) apply(rewrite j1[symmetric], assumption+) apply(rewrite bind_spmf_def) apply(auto 43 split!: option.split dest: rel intro: step.IH intro!: rel_pmf_bind_reflI simp add: map_bind_pmf bind_map_pmf) done next case step case2 thenshow ?caseby(simp add: conversep_iff) next case (step exec_gpv' exec_until_stop') case step: 3 show ?caseusing step.prems apply(simp add: map_spmf_bind_spmf bind_map_spmf gpv.map_sel) apply(rule rel_spmf_bind_reflI) apply(clarsimp simp add: map_spmf_bind_spmf split!: generat.split) apply(rule rel_spmf_bind_reflI) apply clarsimp apply(drule (2) sticking) apply(auto split!: option.split intro: step.IH) done qed note this(1)[OF go] also have"¬ stop s2 ==> ord_spmf (=) (map_spmf (λ(x, s1, s2). (x, s2)) (exec_until_stop joint callee1 (map_gpv Some id gpv) s1 s2 True)) (exec_gpv_stop callee2 gpv s2)" and"ord_spmf (=) (map_spmf (λ(x, s1, y). (x, y)) (exec_until_stop joint callee1 (Done None :: ('a option, 'c, 'r) gpv) s1 s2 b)) (return_spmf (None, s2))" and"stop s2 ==> ord_spmf (=) (map_spmf (λ(x, s1, s2). (x, s2)) (exec_until_stop joint callee1 (map_gpv Some id gpv) s1 s2 False)) (return_spmf (None, s2))" for b using init proof(induction arbitrary: gpv s1 s2 b rule: exec_until_stop.fixp_induct[case_names adm bottom step]) case adm show ?caseby simp
{ case bottom case1show ?caseby simp }
{ case bottom case2show ?caseby simp }
{ case bottom case3show ?caseby simp } next case (step exec_until_stop') case step: 1 show ?caseusing step.prems using [[show_variants]] apply(rewrite exec_gpv.simps) apply(simp add: map_spmf_bind_spmf bind_map_spmf gpv.map_sel) apply(rule ord_spmf_bind_reflI) apply(clarsimp split!: generat.split simp add: map_bind_pmf bind_spmf_def) apply(rewrite j2[symmetric], assumption+) apply(auto 43 split!: option.split dest: rel intro: step.IH intro!: rel_pmf_bind_reflI simp add: bind_map_pmf) done next case step case2thus ?caseby simp next case (step exec_until_stop') case3 thus ?case apply(simp add: map_spmf_bind_spmf o_def) apply(rule ord_spmf_bind_spmfI1) apply(clarsimp split!: generat.split simp add: map_spmf_bind_spmf o_def gpv.map_sel) apply(rule ord_spmf_bind_spmfI1) apply clarsimp apply(drule (2) sticking) apply(clarsimp split!: option.split simp add: step.IH) done qed note this(1)[OF go] finallyshow ?thesis by(rule pmf.rel_mono_strong)(auto elim!: option.rel_cases) qed
end
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.26Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.