Theory More_CC
theory More_CC imports
Constructive_Cryptography.Constructive_Cryptography
begin
section ‹Material for Isabelle library›
lemma eq_alt_conversep: "(=) = (BNF_Def.Grp UNIV id)¯¯"
by(simp add: Grp_def fun_eq_iff)
parametric_constant
swap_parametric [transfer_rule]: prod.swap_def
lemma Sigma_parametric [transfer_rule]: includes lifting_syntax shows
"(rel_set A ===> (A ===> rel_set B) ===> rel_set (rel_prod A B)) Sigma Sigma"
unfolding Sigma_def by transfer_prover
lemma empty_eq_Plus [simp]: "{} = A <+> B ⟷ A = {} ∧ B = {}"
by auto
lemma insert_Inl_Plus [simp]: "insert (Inl x) (A <+> B) = insert x A <+> B" by auto
lemma insert_Inr_Plus [simp]: "insert (Inr x) (A <+> B) = A <+> insert x B" by auto
lemma map_sum_image_Plus [simp]: "map_sum f g ` (A <+> B) = f ` A <+> g ` B"
by(auto intro: rev_image_eqI)
lemma Plus_subset_Plus_iff [simp]: "A <+> B ⊆ C <+> D ⟷ A ⊆ C ∧ B ⊆ D"
by auto
lemma map_sum_eq_Inl_iff: "map_sum f g x = Inl y ⟷ (∃x'. x = Inl x' ∧ y = f x')"
by(cases x) auto
lemma map_sum_eq_Inr_iff: "map_sum f g x = Inr y ⟷ (∃x'. x = Inr x' ∧ y = g x')"
by(cases x) auto
lemma surj_map_sum: "surj (map_sum f g)" if "surj f" "surj g"
apply(safe; simp)
subgoal for x using that
by(cases x)(auto 4 3 intro: image_eqI[where x="Inl _"] image_eqI[where x="Inr _"])
done
lemma bij_map_sumI [simp]: "bij (map_sum f g)" if "bij f" "bij g"
using that by(clarsimp simp add: bij_def sum.inj_map surj_map_sum)
lemma inv_map_sum [simp]:
"⟦ bij f; bij g ⟧ ⟹ inv_into UNIV (map_sum f g) = map_sum (inv_into UNIV f) (inv_into UNIV g)"
by(rule inj_imp_inv_eq)(simp_all add: sum.map_comp sum.inj_map bij_def surj_iff sum.map_id)
context conditionally_complete_lattice begin
lemma admissible_le1I:
"ccpo.admissible lub ord (λx. f x ≤ y)"
if "cont lub ord Sup (≤) f"
by(rule ccpo.admissibleI)(auto simp add: that[THEN contD] intro!: cSUP_least)
lemma admissible_le1_mcont [cont_intro]:
"ccpo.admissible lub ord (λx. f x ≤ y)" if "mcont lub ord Sup (≤) f"
using that by(simp add: admissible_le1I mcont_def)
end
lemma eq_alt_conversep2: "(=) = ((BNF_Def.Grp UNIV id)¯¯)¯¯"
by(auto simp add: Grp_def fun_eq_iff)
lemma nn_integral_indicator_singleton1 [simp]:
assumes [measurable]: "{y} ∈ sets M"
shows "(∫⇧+x. indicator {y} x * f x ∂M) = emeasure M {y} * f y"
by(simp add: mult.commute)
lemma nn_integral_indicator_singleton1' [simp]:
assumes "{y} ∈ sets M"
shows "(∫⇧+x. indicator {x} y * f x ∂M) = emeasure M {y} * f y"
by(subst nn_integral_indicator_singleton1[symmetric, OF assms])(rule nn_integral_cong; simp split: split_indicator)
subsection ‹Probabilities›
lemma pmf_eq_1_iff: "pmf p x = 1 ⟷ p = return_pmf x" (is "?lhs = ?rhs")
proof(rule iffI)
assume ?lhs
have "pmf p i = 0" if "x ≠ i" for i
proof(rule antisym)
have "pmf p i + 1 ≤ pmf p i + pmf p x" using ‹?lhs› by simp
also have "… = measure (measure_pmf p) {i, x}" using that
by(subst measure_pmf.finite_measure_eq_sum_singleton)(simp_all add: pmf.rep_eq)
also have "… ≤ 1" by(rule measure_pmf.subprob_measure_le_1)
finally show "pmf p i ≤ 0" by simp
qed(rule pmf_nonneg)
then show ?rhs if ?lhs
by(intro pmf_eqI)(auto simp add: that split: split_indicator)
qed simp
lemma measure_spmf_cong: "measure (measure_spmf p) A = measure (measure_spmf p) B"
if "A ∩ set_spmf p = B ∩ set_spmf p"
proof -
have "measure (measure_spmf p) A = measure (measure_spmf p) (A ∩ set_spmf p) + measure (measure_spmf p) (A - set_spmf p)"
by(subst measure_spmf.finite_measure_Union[symmetric])(auto intro: arg_cong2[where f=measure])
also have "measure (measure_spmf p) (A - set_spmf p) = 0" by(simp add: measure_spmf_zero_iff)
also have "0 = measure (measure_spmf p) (B - set_spmf p)" by(simp add: measure_spmf_zero_iff)
also have "measure (measure_spmf p) (A ∩ set_spmf p) + … = measure (measure_spmf p) B"
unfolding that by(subst measure_spmf.finite_measure_Union[symmetric])(auto intro: arg_cong2[where f=measure])
finally show ?thesis .
qed
definition weight_spmf' where "weight_spmf' = weight_spmf"
lemma weight_spmf'_parametric [transfer_rule]: "rel_fun (rel_spmf A) (=) weight_spmf' weight_spmf'"
unfolding weight_spmf'_def by(rule weight_spmf_parametric)
lemma bind_spmf_to_nat_on:
"bind_spmf (map_spmf (to_nat_on (set_spmf p)) p) (λn. f (from_nat_into (set_spmf p) n)) = bind_spmf p f"
by(simp add: bind_map_spmf cong: bind_spmf_cong)
lemma try_cond_spmf_fst:
"try_spmf (cond_spmf_fst p x) q = (if x ∈ fst ` set_spmf p then cond_spmf_fst p x else q)"
by (metis cond_spmf_fst_eq_return_None lossless_cond_spmf_fst try_spmf_lossless try_spmf_return_None)
lemma measure_try_spmf:
"measure (measure_spmf (try_spmf p q)) A = measure (measure_spmf p) A + pmf p None * measure (measure_spmf q) A"
proof -
have "emeasure (measure_spmf (try_spmf p q)) A = emeasure (measure_spmf p) A + pmf p None * emeasure (measure_spmf q) A"
by(fold nn_integral_spmf)(simp add: spmf_try_spmf nn_integral_add ennreal_mult' nn_integral_cmult)
then show ?thesis by(simp add: measure_spmf.emeasure_eq_measure ennreal_mult'[symmetric] ennreal_plus[symmetric] del: ennreal_plus)
qed
lemma rel_spmf_OO_trans_strong:
"⟦ rel_spmf R p q; rel_spmf S q r ⟧ ⟹ rel_spmf (R OO eq_onp (λx. x ∈ set_spmf q) OO S) p r"
by(auto intro: rel_spmf_OO_trans rel_spmf_reflI simp add: eq_onp_def)
lemma mcont2mcont_spmf [cont_intro]:
"mcont lub ord Sup (≤) (λp. spmf (f p) x)"
if "mcont lub ord lub_spmf (ord_spmf (=)) f"
using that unfolding mcont_def
apply safe
subgoal by(rule monotone2monotone, rule monotone_spmf; simp)
apply(rule contI)
apply(subst contD[where f=f and luba=lub]; simp)
apply(subst cont_spmf[THEN contD])
apply(erule (2) chain_imageI[OF _ monotoneD])
apply simp
apply(simp add: image_image)
done
lemma ord_spmf_try_spmf2: "ord_spmf R p (try_spmf p q)" if "rel_spmf R p p"
proof -
have "ord_spmf R (bind_pmf p return_pmf) (try_spmf p q)" unfolding try_spmf_def
by(rule rel_pmf_bindI[where R="rel_option R"])
(use that in ‹auto simp add: rel_pmf_return_pmf1 elim!: option.rel_cases›)
then show ?thesis by(simp add: bind_return_pmf')
qed
lemma ord_spmf_lossless_spmfD1:
assumes "ord_spmf R p q"
and "lossless_spmf p"
shows "rel_spmf R p q"
by (metis (no_types, lifting) assms lossless_iff_set_pmf_None option.simps(11) ord_option.cases pmf.rel_mono_strong)
lemma restrict_spmf_mono:
"ord_spmf (=) p q ⟹ ord_spmf (=) (p ↿ A) (q ↿ A)"
by(auto simp add: restrict_spmf_def pmf.rel_map elim!: pmf.rel_mono_strong elim: ord_option.cases)
lemma restrict_lub_spmf:
assumes chain: "Complete_Partial_Order.chain (ord_spmf (=)) Y"
shows "restrict_spmf (lub_spmf Y) A = lub_spmf ((λp. restrict_spmf p A) ` Y)" (is "?lhs = ?rhs")
proof(cases "Y = {}")
case Y: False
have chain': "Complete_Partial_Order.chain (ord_spmf (=)) ((λp. p ↿ A) ` Y)"
using chain by(rule chain_imageI)(auto intro: restrict_spmf_mono)
show ?thesis by(rule spmf_eqI)(simp add: spmf_lub_spmf[OF chain'] Y image_image spmf_restrict_spmf spmf_lub_spmf[OF chain])
qed simp
lemma mono2mono_restrict_spmf [THEN spmf.mono2mono]:
shows monotone_restrict_spmf: "monotone (ord_spmf (=)) (ord_spmf (=)) (λp. p ↿ A)"
by(rule monotoneI)(rule restrict_spmf_mono)
lemma mcont2mcont_restrict_spmf [THEN spmf.mcont2mcont, cont_intro]:
shows mcont_restrict_spmf: "mcont lub_spmf (ord_spmf (=)) lub_spmf (ord_spmf (=)) (λp. restrict_spmf p A)"
using monotone_restrict_spmf by(rule mcontI)(simp add: contI restrict_lub_spmf)
lemma ord_spmf_case_option: "ord_spmf R (case x of None ⇒ a | Some y ⇒ b y) (case x of None ⇒ a' | Some y ⇒ b' y)"
if "ord_spmf R a a'" "⋀y. ord_spmf R (b y) (b' y)" using that by(cases x) auto
lemma ord_spmf_map_spmfI: "ord_spmf (=) (map_spmf f p) (map_spmf f q)" if "ord_spmf (=) p q"
using that by(auto simp add: pmf.rel_map elim!: pmf.rel_mono_strong ord_option.cases)
subsubsection ‹Conditional probabilities›
lemma mk_lossless_cond_spmf [simp]: "mk_lossless (cond_spmf p A) = cond_spmf p A"
by(simp add: cond_spmf_alt)
context
fixes p :: "'a pmf"
and f :: "'a ⇒ 'b pmf"
and A :: "'b set"
and F :: "'a ⇒ real"
defines "F ≡ λx. pmf p x * measure (measure_pmf (f x)) A / measure (measure_pmf (bind_pmf p f)) A"
begin
definition cond_bind_pmf :: "'a pmf" where "cond_bind_pmf = embed_pmf F"
lemma cond_bind_pmf_nonneg: "F x ≥ 0"
by(simp add: F_def)
context assumes defined: "A ∩ (⋃x∈set_pmf p. set_pmf (f x)) ≠ {}" begin
private lemma nonzero: "measure (measure_pmf (bind_pmf p f)) A > 0"
using defined by(auto 4 3 intro: measure_pmf_posI)
lemma cond_bind_pmf_prob: "(∫⇧+ x. F x ∂count_space UNIV) = 1"
proof -
have nonzero': "(∫⇧+ x. ennreal (pmf p x) * ennreal (measure_pmf.prob (f x) A) ∂count_space UNIV) ≠ 0"
using defined by(auto simp add: nn_integral_0_iff_AE AE_count_space pmf_eq_0_set_pmf measure_pmf_zero_iff)
have finite: "(∫⇧+ x. ennreal (pmf p x) * ennreal (measure_pmf.prob (f x) A) ∂count_space UNIV) < ⊤" (is "?lhs < _")
proof(rule order.strict_trans1)
show "?lhs ≤ (∫⇧+ x. ennreal (pmf p x) * 1 ∂count_space UNIV)"
by(rule nn_integral_mono)(simp add: mult_left_le)
show "… < ⊤" by(simp add: nn_integral_pmf_eq_1)
qed
have "(∫⇧+ x. F x ∂count_space UNIV) =
(∑⇧+ x. ennreal (pmf p x * measure_pmf.prob (f x) A)) / emeasure (measure_pmf (bind_pmf p f)) A"
using nonzero unfolding F_def measure_pmf.emeasure_eq_measure
by(simp add: divide_ennreal[symmetric] divide_ennreal_def nn_integral_multc)
also have "… = 1" unfolding emeasure_bind_pmf
by(simp add: measure_pmf.emeasure_eq_measure nn_integral_measure_pmf ennreal_mult' nonzero' finite)
finally show ?thesis .
qed
lemma pmf_cond_bind_pmf: "pmf cond_bind_pmf x = F x"
unfolding cond_bind_pmf_def by(rule pmf_embed_pmf[OF cond_bind_pmf_nonneg cond_bind_pmf_prob])
lemma set_cond_bind_pmf: "set_pmf cond_bind_pmf = {x∈set_pmf p. set_pmf (f x) ∩ A ≠ {}}"
unfolding cond_bind_pmf_def
by(subst set_embed_pmf[OF cond_bind_pmf_nonneg cond_bind_pmf_prob])
(auto simp add: F_def pmf_eq_0_set_pmf measure_pmf_zero_iff)
lemma cond_bind_pmf: "cond_pmf (bind_pmf p f) A = bind_pmf cond_bind_pmf (λx. cond_pmf (f x) A)"
(is "?lhs = ?rhs")
proof(rule pmf_eqI)
fix i
have "ennreal (pmf ?lhs i) = ennreal (pmf ?rhs i)"
proof(cases "i ∈ A")
case True
have "ennreal (pmf ?lhs i) = (∫⇧+ x. ennreal (pmf p x) * ennreal (pmf (f x) i) / ennreal (measure_pmf.prob (p ⤜ f) A) ∂count_space UNIV)"
using True defined
by(simp add: pmf_cond bind_UNION Int_commute divide_ennreal[symmetric] nonzero ennreal_pmf_bind)
(simp add: divide_ennreal_def nn_integral_multc[symmetric] nn_integral_measure_pmf)
also have "… = (∫⇧+ x. ennreal (F x) * ennreal (pmf (cond_pmf (f x) A) i) ∂count_space UNIV)"
using True nonzero
apply(intro nn_integral_cong)
subgoal for x
by(clarsimp simp add: F_def ennreal_mult'[symmetric] divide_ennreal)
(cases "measure_pmf.prob (f x) A = 0"; auto simp add: pmf_cond pmf_eq_0_set_pmf measure_pmf_zero_iff)
done
also have "… = ennreal (pmf ?rhs i)"
by(simp add: ennreal_pmf_bind nn_integral_measure_pmf pmf_cond_bind_pmf)
finally show ?thesis .
next
case False
then show ?thesis using defined
by(simp add: pmf_cond bind_UNION Int_commute pmf_eq_0_set_pmf set_cond_bind_pmf)
qed
then show "pmf ?lhs i = pmf ?rhs i" by simp
qed
end
end
lemma cond_spmf_try1:
"cond_spmf (try_spmf p q) A = cond_spmf p A" if "set_spmf q ∩ A = {}"
apply(rule spmf_eqI)
using that
apply(auto simp add: spmf_try_spmf measure_try_spmf measure_spmf_zero_iff)
apply(subst (2) spmf_eq_0_set_spmf[THEN iffD2])
apply blast
apply simp
apply(simp add: measure_try_spmf measure_spmf_zero_iff)
done
lemma cond_spmf_cong: "cond_spmf p A = cond_spmf p B" if "A ∩ set_spmf p = B ∩ set_spmf p"
apply(rule spmf_eqI)
using that by(auto simp add: measure_spmf_zero_iff spmf_eq_0_set_spmf measure_spmf_cong[OF that])
lemma cond_spmf_pair_spmf:
"cond_spmf (pair_spmf p q) (A × B) = pair_spmf (cond_spmf p A) (cond_spmf q B)" (is "?lhs = ?rhs")
proof(rule spmf_eqI)
show "spmf ?lhs i = spmf ?rhs i" for i
proof(cases i)
case i [simp]: (Pair a b)
then show ?thesis by(simp add: measure_pair_spmf_times)
qed
qed
lemma cond_spmf_pair_spmf1:
"cond_spmf_fst (map_spmf (λ((x, s'), y). (f x, s', y)) (pair_spmf p q)) x =
pair_spmf (cond_spmf_fst (map_spmf (λ(x, s'). (f x, s')) p) x) q" (is "?lhs = ?rhs")
if "lossless_spmf q"
proof -
have "?lhs = map_spmf (λ((_, s'), y). (s', y)) (cond_spmf (pair_spmf p q) ((λ((x, s'), y). (f x, s', y)) -` ({x} × UNIV)))"
by(simp add: cond_spmf_fst_def spmf.map_comp o_def split_def)
also have "((λ((x, s'), y). (f x, s', y)) -` ({x} × UNIV)) = ((λ(x, y). (f x, y)) -` ({x} × UNIV)) × UNIV"
by(auto)
also have "map_spmf (λ((_, s'), y). (s', y)) (cond_spmf (pair_spmf p q) …) = ?rhs"
by(simp add: cond_spmf_fst_def cond_spmf_pair_spmf that spmf.map_comp pair_map_spmf1 apfst_def map_prod_def split_def)
finally show ?thesis .
qed
lemma try_cond_spmf: "try_spmf (cond_spmf p A) q = (if set_spmf p ∩ A ≠ {} then cond_spmf p A else q)"
apply(clarsimp simp add: cond_spmf_def lossless_iff_set_pmf_None intro!: try_spmf_lossless)
apply(subst (asm) set_cond_pmf)
apply(auto simp add: in_set_spmf)
done
lemma cond_spmf_try2:
"cond_spmf (try_spmf p q) A = (if lossless_spmf p then return_pmf None else cond_spmf q A)" if "set_spmf p ∩ A = {}"
apply(rule spmf_eqI)
using that
apply(auto simp add: spmf_try_spmf measure_try_spmf measure_spmf_zero_iff lossless_iff_pmf_None)
apply(subst spmf_eq_0_set_spmf[THEN iffD2])
apply blast
apply(simp add: measure_spmf_zero_iff[THEN iffD2])
done
definition cond_bind_spmf :: "'a spmf ⇒ ('a ⇒ 'b spmf) ⇒ 'b set ⇒ 'a spmf" where
"cond_bind_spmf p f A =
(if ∃x∈set_spmf p. set_spmf (f x) ∩ A ≠ {} then
cond_bind_pmf p (λx. case x of None ⇒ return_pmf None | Some x ⇒ f x) (Some ` A)
else return_pmf None)"
context begin
private lemma defined: "⟦ y ∈ set_spmf (f x); y ∈ A; x ∈ set_spmf p ⟧
⟹ Some ` A ∩ (⋃x∈set_pmf p. set_pmf (case x of None ⇒ return_pmf None | Some x ⇒ f x)) ≠ {}"
by(fastforce simp add: in_set_spmf bind_spmf_def)
lemma spmf_cond_bind_spmf [simp]:
"spmf (cond_bind_spmf p f A) x = spmf p x * measure (measure_spmf (f x)) A / measure (measure_spmf (bind_spmf p f)) A"
by(clarsimp simp add: cond_bind_spmf_def measure_spmf_zero_iff bind_UNION pmf_cond_bind_pmf defined split!: if_split)
(fastforce simp add: in_set_spmf bind_spmf_def measure_measure_spmf_conv_measure_pmf)+
lemma set_cond_bind_spmf [simp]:
"set_spmf (cond_bind_spmf p f A) = {x∈set_spmf p. set_spmf (f x) ∩ A ≠ {}}"
by(clarsimp simp add: cond_bind_spmf_def set_spmf_def bind_UNION)
(subst set_cond_bind_pmf; fastforce simp add: measure_measure_spmf_conv_measure_pmf)
lemma cond_bind_spmf: "cond_spmf (bind_spmf p f) A = bind_spmf (cond_bind_spmf p f A) (λx. cond_spmf (f x) A)"
by(auto simp add: cond_spmf_def bind_UNION cond_bind_spmf_def split!: if_splits)
(fastforce split: option.splits simp add: cond_bind_pmf set_cond_bind_pmf defined in_set_spmf bind_spmf_def intro!: bind_pmf_cong[OF refl])
end
lemma cond_spmf_fst_parametric [transfer_rule]: includes lifting_syntax shows
"(rel_spmf (rel_prod (=) B) ===> (=) ===> rel_spmf B) cond_spmf_fst cond_spmf_fst"
apply(rule rel_funI)+
apply(clarsimp simp add: cond_spmf_fst_def spmf_rel_map elim!: rel_spmfE)
subgoal for x pq
by(subst (1 2) cond_spmf_cong[where B="fst -` ({x} × UNIV) ∩ snd -` ({x} × UNIV)"])
(fastforce intro: rel_spmf_reflI)+
done
lemma cond_spmf_fst_map_prod:
"cond_spmf_fst (map_spmf (λ(x, y). (f x, g x y)) p) (f x) = map_spmf (g x) (cond_spmf_fst p x)"
if "inj_on f (insert x (fst ` set_spmf p))"
proof -
have "cond_spmf p ((λ(x, y). (f x, g x y)) -` ({f x} × UNIV)) = cond_spmf p (((λ(x, y). (f x, g x y)) -` ({f x} × UNIV)) ∩ set_spmf p)"
by(rule cond_spmf_cong) simp
also have "((λ(x, y). (f x, g x y)) -` ({f x} × UNIV)) ∩ set_spmf p = ({x} × UNIV) ∩ set_spmf p"
using that by(auto 4 3 dest: inj_onD intro: rev_image_eqI)
also have "cond_spmf p … = cond_spmf p ({x} × UNIV)"
by(rule cond_spmf_cong) simp
finally show ?thesis
by(auto simp add: cond_spmf_fst_def spmf.map_comp o_def split_def intro: map_spmf_cong)
qed
lemma cond_spmf_fst_map_prod_inj:
"cond_spmf_fst (map_spmf (λ(x, y). (f x, g x y)) p) (f x) = map_spmf (g x) (cond_spmf_fst p x)"
if "inj f"
apply(rule cond_spmf_fst_map_prod)
using that by(simp add: inj_on_def)
definition cond_bind_spmf_fst :: "'a spmf ⇒ ('a ⇒ 'b spmf) ⇒ 'b ⇒ 'a spmf" where
"cond_bind_spmf_fst p f x = cond_bind_spmf p (map_spmf (λb. (b, ())) ∘ f) ({x} × UNIV)"
lemma cond_bind_spmf_fst_map_spmf_fst:
"cond_bind_spmf_fst p (map_spmf fst ∘ f) x = cond_bind_spmf p f ({x} × UNIV)" (is "?lhs = ?rhs")
proof -
have [simp]: "(λx. (fst x, ())) -` ({x} × UNIV) = {x} × UNIV" by auto
have "?lhs = cond_bind_spmf p (λx. map_spmf (λx. (fst x, ())) (f x)) ({x} × UNIV)"
by(simp add: cond_bind_spmf_fst_def spmf.map_comp o_def)
also have "… = ?rhs" by(rule spmf_eqI)(simp add: measure_map_spmf map_bind_spmf[unfolded o_def, symmetric])
finally show ?thesis .
qed
lemma cond_spmf_fst_bind: "cond_spmf_fst (bind_spmf p f) x =
bind_spmf (cond_bind_spmf_fst p (map_spmf fst ∘ f) x) (λy. cond_spmf_fst (f y) x)"
by(simp add: cond_spmf_fst_def cond_bind_spmf map_bind_spmf cond_bind_spmf_fst_map_spmf_fst)(simp add: o_def)
lemma spmf_cond_bind_spmf_fst [simp]:
"spmf (cond_bind_spmf_fst p f x) i = spmf p i * spmf (f i) x / spmf (bind_spmf p f) x"
by(simp add: cond_bind_spmf_fst_def)
(auto simp add: spmf_conv_measure_spmf measure_map_spmf map_bind_spmf[symmetric] intro!: arg_cong2[where f="(/)"] arg_cong2[where f="(*)"] arg_cong2[where f="measure"])
lemma set_cond_bind_spmf_fst [simp]:
"set_spmf (cond_bind_spmf_fst p f x) = {y ∈ set_spmf p. x ∈ set_spmf (f y)}"
by(auto simp add: cond_bind_spmf_fst_def intro: rev_image_eqI)
lemma map_cond_spmf_fst: "map_spmf f (cond_spmf_fst p x) = cond_spmf_fst (map_spmf (apsnd f) p) x"
by(auto simp add: cond_spmf_fst_def spmf.map_comp intro!: map_spmf_cong arg_cong2[where f="cond_spmf"])
lemma cond_spmf_fst_try1:
"cond_spmf_fst (try_spmf p q) x = cond_spmf_fst p x" if "x ∉ fst ` set_spmf q"
using that
apply(simp add: cond_spmf_fst_def)
apply(subst cond_spmf_try1)
apply(auto intro: rev_image_eqI)
done
lemma cond_spmf_fst_try2:
"cond_spmf_fst (try_spmf p q) x = (if lossless_spmf p then return_pmf None else cond_spmf_fst q x)" if "x ∉ fst ` set_spmf p"
using that
apply(simp add: cond_spmf_fst_def split!: if_split)
apply (metis cond_spmf_fst_def cond_spmf_fst_eq_return_None)
by (metis cond_spmf_fst_def cond_spmf_try2 lossless_cond_spmf lossless_cond_spmf_fst lossless_map_spmf)
lemma cond_spmf_fst_map_inj:
"cond_spmf_fst (map_spmf (apfst f) p) (f x) = cond_spmf_fst p x" if "inj f"
by(auto simp add: cond_spmf_fst_def spmf.map_comp intro!: map_spmf_cong arg_cong2[where f=cond_spmf] dest: injD[OF that])
lemma cond_spmf_fst_pair_spmf1:
"cond_spmf_fst (map_spmf (λ(x, y). (f x, g x y)) (pair_spmf p q)) a =
bind_spmf (cond_spmf_fst (map_spmf (λx. (f x, x)) p) a) (λx. map_spmf (g x) (mk_lossless q))" (is "?lhs = ?rhs")
proof -
have "(λ(x, y). (f x, g x y)) -` ({a} × UNIV) = f -` {a} × UNIV" by(auto)
moreover have "(λx. (f x, x)) -` ({a} × UNIV) = f -` {a}" by auto
ultimately show ?thesis
by(simp add: cond_spmf_fst_def spmf.map_comp o_def split_beta cond_spmf_pair_spmf)
(simp add: pair_spmf_alt_def map_bind_spmf o_def map_spmf_conv_bind_spmf)
qed
lemma cond_spmf_fst_return_spmf':
"cond_spmf_fst (return_spmf (x, y)) z = (if x = z then return_spmf y else return_pmf None)"
by(simp add: cond_spmf_fst_def)
section ‹Material for CryptHOL›
lemma left_gpv_lift_spmf [simp]: "left_gpv (lift_spmf p) = lift_spmf p"
by(rule gpv.expand)(simp add: spmf.map_comp o_def)
lemma right_gpv_lift_spmf [simp]: "right_gpv (lift_spmf p) = lift_spmf p"
by(rule gpv.expand)(simp add: spmf.map_comp o_def)
lemma map'_lift_spmf: "map_gpv' f g h (lift_spmf p) = lift_spmf (map_spmf f p)"
by(rule gpv.expand)(simp add: gpv.map_sel spmf.map_comp o_def)
lemma in_set_sample_uniform [simp]: "x ∈ set_spmf (sample_uniform n) ⟷ x < n"
by(simp add: sample_uniform_def)
lemma (in cyclic_group) inj_on_generator_iff [simp]: "⟦ x < order G; y < order G ⟧ ⟹ ❙g [^] x = ❙g [^] y ⟷ x = y"
using inj_on_generator by(auto simp add: inj_on_def)
lemma map_ℐ_bot [simp]: "map_ℐ f g ⊥ = ⊥"
unfolding bot_ℐ_def map_ℐ_ℐ_uniform by simp
lemma map_ℐ_Inr_plus [simp]: "map_ℐ Inr f (ℐ1 ⊕⇩ℐ ℐ2) = map_ℐ id (f ∘ Inr) ℐ2"
by(rule ℐ_eqI) auto
lemma interaction_bound_map_gpv'_le:
defines "ib ≡ interaction_bound"
shows "interaction_bound consider (map_gpv' f g h gpv) ≤ ib (consider ∘ g) gpv"
proof(induction arbitrary: gpv rule: interaction_bound_fixp_induct)
case adm show ?case by simp
case bottom show ?case by simp
case (step interaction_bound')
show ?case unfolding ib_def
by(subst interaction_bound.simps)
(auto simp add: image_comp ib_def split: generat.split intro!: SUP_mono rev_bexI step.IH[unfolded ib_def])
qed
lemma interaction_bounded_by_map_gpv' [interaction_bound]:
assumes "interaction_bounded_by (consider ∘ g) gpv n"
shows "interaction_bounded_by consider (map_gpv' f g h gpv) n"
using assms interaction_bound_map_gpv'_le[of "consider" f g h gpv] by(simp add: interaction_bounded_by.simps)
lemma map_gpv'_bind_gpv:
"map_gpv' f g h (bind_gpv gpv F) = bind_gpv (map_gpv' id g h gpv) (λx. map_gpv' f g h (F x))"
by(coinduction arbitrary: gpv rule: gpv.coinduct_strong)
(auto simp del: bind_gpv_sel' simp add: bind_gpv.sel spmf_rel_map bind_map_spmf generat.rel_map rel_fun_def intro!: rel_spmf_bind_reflI rel_spmf_reflI generat.rel_refl_strong split!: generat.split)
lemma exec_gpv_map_gpv':
"exec_gpv callee (map_gpv' f g h gpv) s =
map_spmf (map_prod f id) (exec_gpv (map_fun id (map_fun g (map_spmf (map_prod h id))) callee) gpv s)"
using exec_gpv_parametric'[
where S="(=)" and CALL="BNF_Def.Grp UNIV g" and R="conversep (BNF_Def.Grp UNIV h)" and A="BNF_Def.Grp UNIV f",
unfolded rel_gpv''_Grp, simplified]
apply(subst (asm) (2) conversep_eq[symmetric])
apply(subst (asm) prod.rel_conversep)
apply(subst (asm) (2 4) eq_alt)
apply(subst (asm) prod.rel_Grp)
apply simp
apply(subst (asm) spmf_rel_conversep)
apply(subst (asm) option.rel_Grp)
apply(subst (asm) pmf.rel_Grp)
apply simp
apply(subst (asm) prod.rel_Grp)
apply simp
apply(subst (asm) (1 3) conversep_conversep[symmetric])
apply(subst (asm) rel_fun_conversep)
apply(subst (asm) rel_fun_Grp)
apply(subst (asm) rel_fun_conversep)
apply simp
apply(simp add: option.rel_Grp pmf.rel_Grp fun.rel_Grp)
apply(simp add: rel_fun_def BNF_Def.Grp_def o_def map_fun_def)
apply(erule allE)+
apply(drule fun_cong)
apply(erule trans)
apply simp
done
lemma colossless_gpv_sub_gpvs:
assumes "colossless_gpv ℐ gpv" "gpv' ∈ sub_gpvs ℐ gpv"
shows "colossless_gpv ℐ gpv'"
using assms(2,1) by(induction)(auto dest: colossless_gpvD)
lemma pfinite_gpv_sub_gpvs:
assumes "pfinite_gpv ℐ gpv" "gpv' ∈ sub_gpvs ℐ gpv" "ℐ ⊢g gpv √"
shows "pfinite_gpv ℐ gpv'"
using assms(2,1,3) by(induction)(auto dest: pfinite_gpv_ContD WT_gpvD)
lemma pfinite_gpv_id_oracle [simp]: "pfinite_gpv ℐ (id_oracle s x)" if "x ∈ outs_ℐ ℐ"
by(simp add: id_oracle_def pgen_lossless_gpv_PauseI[OF that])
subsection ‹@{term try_gpv}›
lemma plossless_gpv_try_gpvI:
assumes "pfinite_gpv ℐ gpv"
and "¬ colossless_gpv ℐ gpv ⟹ plossless_gpv ℐ gpv'"
shows "plossless_gpv ℐ (TRY gpv ELSE gpv')"
using assms unfolding pgen_lossless_gpv_def
by(cases "colossless_gpv ℐ gpv")(simp cong: expectation_gpv_cong_fail, simp)
lemma WT_gpv_try_gpvI [WT_intro]:
assumes "ℐ ⊢g gpv √"
and "¬ colossless_gpv ℐ gpv ⟹ ℐ ⊢g gpv' √"
shows "ℐ ⊢g try_gpv gpv gpv' √"
using assms by(coinduction arbitrary: gpv)(auto 4 4 dest: WT_gpvD colossless_gpvD split: if_split_asm)
lemma (in callee_invariant_on) exec_gpv_try_gpv:
fixes exec_gpv1
defines "exec_gpv1 ≡ exec_gpv"
assumes WT: "ℐ ⊢g gpv √"
and pfinite: "pfinite_gpv ℐ gpv"
and I: "I s"
and f: "⋀s. I s ⟹ f (x, s) = z"
and lossless: "⋀s x. ⟦x ∈ outs_ℐ ℐ; I s⟧ ⟹ lossless_spmf (callee s x)"
shows "map_spmf f (exec_gpv callee (try_gpv gpv (Done x)) s) =
try_spmf (map_spmf f (exec_gpv1 callee gpv s)) (return_spmf z)"
(is "?lhs = ?rhs")
proof -
note [[show_variants]]
have le: "ord_spmf (=) ?lhs ?rhs" using WT I
proof(induction arbitrary: gpv s rule: exec_gpv_fixp_induct)
case adm show ?case by simp
case bottom show ?case by simp
case (step exec_gpv')
show ?case using step.prems unfolding exec_gpv1_def
apply(subst exec_gpv.simps)
apply(simp add: map_spmf_bind_spmf)
apply(subst (1 2) try_spmf_def)
apply(simp add: map_bind_pmf bind_spmf_pmf_assoc o_def)
apply(simp add: bind_spmf_def bind_map_pmf bind_assoc_pmf)
apply(rule rel_pmf_bindI[where R="eq_onp (λx. x ∈ set_pmf (the_gpv gpv))"])
apply(rule pmf.rel_refl_strong)
apply(simp add: eq_onp_def)
apply(clarsimp split!: option.split generat.split simp add: bind_return_pmf f map_spmf_bind_spmf o_def eq_onp_def)
apply(simp add: bind_spmf_def bind_assoc_pmf)
subgoal for out c
apply(rule rel_pmf_bindI[where R="eq_onp (λx. x ∈ set_pmf (callee s out))"])
apply(rule pmf.rel_refl_strong)
apply(simp add: eq_onp_def)
apply(clarsimp split!: option.split simp add: eq_onp_def)
apply(simp add: in_set_spmf[symmetric])
apply(rule spmf.leq_trans)
apply(rule step.IH)
apply(frule (1) WT_gpvD)
apply(erule (1) WT_gpvD)
apply(drule WT_callee)
apply(erule (2) WT_calleeD)
apply(frule (1) WT_gpvD)
apply(erule (2) callee_invariant)
apply(simp add: try_spmf_def exec_gpv1_def)
done
done
qed
have "lossless_spmf ?lhs"
apply simp
apply(rule plossless_exec_gpv)
apply(rule plossless_gpv_try_gpvI)
apply(rule pfinite)
apply simp
apply(rule WT_gpv_try_gpvI)
apply(simp add: WT)
apply simp
apply(simp add: lossless)
apply(simp add: I)
done
from ord_spmf_lossless_spmfD1[OF le this] show ?thesis by(simp add: spmf_rel_eq)
qed
lemma try_gpv_bind_gen_lossless':
assumes lossless: "gen_lossless_gpv b ℐ gpv"
and WT1: "ℐ ⊢g gpv √"
and WT2: "ℐ ⊢g gpv' √"
and WTf: "⋀x. x ∈ results_gpv ℐ gpv ⟹ ℐ ⊢g f x √"
shows "eq_ℐ_gpv (=) ℐ (TRY bind_gpv gpv f ELSE gpv') (bind_gpv gpv (λx. TRY f x ELSE gpv'))"
using lossless WT1 WTf
proof(coinduction arbitrary: gpv)
case (eq_ℐ_gpv gpv)
note [simp] = spmf_rel_map generat.rel_map map_spmf_bind_spmf
and [intro!] = rel_spmf_reflI rel_generat_reflI rel_funI
show ?case using gen_lossless_gpvD[OF eq_ℐ_gpv(1)] WT_gpvD[OF eq_ℐ_gpv(2)] WT_gpvD[OF WT2] WT_gpvD[OF eq_ℐ_gpv(3)[rule_format, OF results_gpv.Pure]] WT2
apply(auto simp del: bind_gpv_sel' simp add: bind_gpv.sel try_spmf_bind_spmf_lossless generat.map_comp o_def intro!: rel_spmf_bind_reflI rel_spmf_try_spmf split!: generat.split)
apply(auto 4 4 intro!: eq_ℐ_gpv(3)[rule_format] eq_ℐ_gpv_reflI eq_ℐ_generat_reflI intro: results_gpv.IO WT_intro)
done
qed
lemmas try_gpv_bind_lossless' = try_gpv_bind_gen_lossless'[where b=False]
and try_gpv_bind_colossless' = try_gpv_bind_gen_lossless'[where b=True]
lemma try_gpv_bind_gpv:
"try_gpv (bind_gpv gpv f) gpv' =
bind_gpv (try_gpv (map_gpv Some id gpv) (Done None)) (λx. case x of None ⇒ gpv' | Some x' ⇒ try_gpv (f x') gpv')"
by(coinduction arbitrary: gpv rule: gpv.coinduct_strong)
(auto simp add: rel_fun_def generat.rel_map bind_return_pmf spmf_rel_map map_bind_spmf o_def bind_gpv.sel bind_map_spmf try_spmf_def bind_spmf_def spmf.map_comp bind_map_pmf bind_assoc_pmf gpv.map_sel simp del: bind_gpv_sel' intro!: rel_pmf_bind_reflI generat.rel_refl_strong rel_spmf_reflI split!: option.split generat.split)
lemma bind_gpv_try_gpv_map_Some:
"bind_gpv (try_gpv (map_gpv Some id gpv) (Done None)) (λx. case x of None ⇒ Fail | Some y ⇒ f y) =
bind_gpv gpv f"
by(coinduction arbitrary: gpv rule: gpv.coinduct_strong)
(auto simp add: bind_gpv.sel map_bind_spmf bind_map_spmf try_spmf_def bind_spmf_def spmf_rel_map bind_map_pmf gpv.map_sel bind_assoc_pmf bind_return_pmf generat.rel_map rel_fun_def simp del: bind_gpv_sel' intro!: rel_pmf_bind_reflI rel_spmf_reflI generat.rel_refl_strong split!: option.split generat.split)
lemma try_gpv_left_gpv:
assumes "ℐ ⊢g gpv √" and WT2: "ℐ ⊢g gpv' √"
shows "eq_ℐ_gpv (=) (ℐ ⊕⇩ℐ ℐ') (try_gpv (left_gpv gpv) (left_gpv gpv')) (left_gpv (try_gpv gpv gpv'))"
using assms(1)
apply(coinduction arbitrary: gpv)
apply(auto simp add: map_try_spmf spmf.map_comp o_def generat.map_comp spmf_rel_map intro!: rel_spmf_try_spmf rel_spmf_reflI)
subgoal for gpv generat by(cases generat)(auto dest: WT_gpvD)
subgoal for gpv generat using WT2
by(cases generat)(auto 4 4 dest: WT_gpvD intro!: eq_ℐ_gpv_reflI WT_gpv_left_gpv)
done
lemma try_gpv_right_gpv:
assumes "ℐ' ⊢g gpv √" and WT2: "ℐ' ⊢g gpv' √"
shows "eq_ℐ_gpv (=) (ℐ ⊕⇩ℐ ℐ') (try_gpv (right_gpv gpv) (right_gpv gpv')) (right_gpv (try_gpv gpv gpv'))"
using assms(1)
apply(coinduction arbitrary: gpv)
apply(auto simp add: map_try_spmf spmf.map_comp o_def generat.map_comp spmf_rel_map intro!: rel_spmf_try_spmf rel_spmf_reflI)
subgoal for gpv generat by(cases generat)(auto dest: WT_gpvD)
subgoal for gpv generat using WT2
by(cases generat)(auto 4 4 dest: WT_gpvD intro!: eq_ℐ_gpv_reflI WT_gpv_right_gpv)
done
lemma bind_try_Done_Fail: "bind_gpv (TRY gpv ELSE Done x) f = bind_gpv gpv f" if "f x = Fail"
apply(coinduction arbitrary: gpv rule: gpv.coinduct_strong)
apply(auto simp del: bind_gpv_sel' simp add: bind_gpv.sel map_bind_spmf bind_map_spmf try_spmf_def bind_spmf_def map_bind_pmf bind_assoc_pmf bind_map_pmf bind_return_pmf spmf.map_comp o_def that rel_fun_def intro!: rel_pmf_bind_reflI rel_spmf_reflI generat.rel_refl_strong split!: option.split generat.split)
done
lemma inline_map_gpv':
"inline callee (map_gpv' f g h gpv) s =
map_gpv (apfst f) id (inline (map_fun id (map_fun g (map_gpv (apfst h) id)) callee) gpv s)"
using inline_parametric'[where S="(=)" and C="BNF_Def.Grp UNIV g" and R="conversep (BNF_Def.Grp UNIV h)" and A="BNF_Def.Grp UNIV f" and C'="(=)" and R'="(=)"]
apply(subst (asm) (2 3 8) eq_alt_conversep)
apply(subst (asm) (1 3 4 5) eq_alt)
apply(subst (asm) (1) eq_alt_conversep2)
apply(unfold prod.rel_conversep rel_gpv''_conversep prod.rel_Grp rel_gpv''_Grp)
apply(force simp add: rel_fun_def Grp_def map_gpv_conv_map_gpv' map_fun_def[abs_def] o_def apfst_def)
done
lemma interaction_bound_try_gpv:
fixes "consider" defines "ib ≡ interaction_bound consider"
shows "interaction_bound consider (try_gpv gpv gpv') ≤ ib gpv + ib gpv'"
proof(induction arbitrary: gpv gpv' rule: interaction_bound_fixp_induct)
case adm show ?case by simp
case bottom show ?case by simp
case (step interaction_bound')
show ?case unfolding ib_def
apply(clarsimp simp add: generat.map_comp image_image o_def case_map_generat cong del: generat.case_cong split!: if_split generat.split intro!: SUP_least)
subgoal
apply(subst interaction_bound.simps)
apply simp
apply(subst Sup_image_eadd1[symmetric])
apply clarsimp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(simp add: iadd_Suc)
apply(subst Sup_image_eadd1[symmetric])
apply simp
apply(rule SUP_mono)
apply simp
apply(rule exI)
apply(rule step.IH[unfolded ib_def])
done
subgoal
apply(subst interaction_bound.simps)
apply simp
apply(subst Sup_image_eadd1[symmetric])
apply clarsimp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(subst Sup_image_eadd1[symmetric])
apply simp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(rule step.IH[unfolded ib_def])
done
subgoal
apply(subst interaction_bound.simps)
apply simp
apply(subst Sup_image_eadd1[symmetric])
apply clarsimp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(simp add: iadd_Suc)
apply(subst Sup_image_eadd1[symmetric])
apply simp
apply(rule SUP_mono)
apply simp
apply(rule exI)
apply(rule step.IH[unfolded ib_def])
done
subgoal
apply(subst interaction_bound.simps)
apply simp
apply(subst Sup_image_eadd1[symmetric])
apply clarsimp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(subst Sup_image_eadd1[symmetric])
apply simp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(rule step.IH[unfolded ib_def])
done
subgoal
apply(subst (2) interaction_bound.simps)
apply simp
apply(subst Sup_image_eadd2[symmetric])
apply clarsimp
apply simp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(simp add: iadd_Suc_right)
apply(subst Sup_image_eadd2[symmetric])
apply clarsimp
apply(rule SUP_mono)
apply clarsimp
apply(rule exI)
apply(rule order_trans)
apply(rule step.hyps)
apply(rule enat_le_plus_same)
done
subgoal
apply(subst (2) interaction_bound.simps)
apply simp
apply(subst Sup_image_eadd2[symmetric])
apply clarsimp
apply simp
apply(rule SUP_upper2)
apply(rule rev_image_eqI)
apply simp
apply simp
apply(subst Sup_image_eadd2[symmetric])
apply clarsimp
apply(rule SUP_upper2)
apply(rule imageI)
apply simp
apply(rule order_trans)
apply(rule step.hyps)
apply(rule enat_le_plus_same)
done
done
qed
lemma interaction_bounded_by_try_gpv [interaction_bound]:
"interaction_bounded_by consider (try_gpv gpv1 gpv2) (bound1 + bound2)"
if "interaction_bounded_by consider gpv1 bound1" "interaction_bounded_by consider gpv2 bound2"
using that interaction_bound_try_gpv[of "consider" gpv1 gpv2]
by(simp add: interaction_bounded_by.simps)(meson add_left_mono_trans add_right_mono le_left_mono)
subsection ‹term ‹gpv_stop››
lemma interaction_bounded_by_gpv_stop [interaction_bound]:
assumes "interaction_bounded_by consider gpv n"
shows "interaction_bounded_by consider (gpv_stop gpv) n"
using assms by(simp add: interaction_bounded_by.simps)
context includes ℐ.lifting begin
lift_definition stop_ℐ :: "('a, 'b) ℐ ⇒ ('a, 'b option) ℐ" is
"λresp x. if (resp x = {}) then {} else insert None (Some ` resp x)" .
lemma outs_stop_ℐ [simp]: "outs_ℐ (stop_ℐ ℐ) = outs_ℐ ℐ"
by transfer auto
lemma responses_stop_ℐ [simp]:
"responses_ℐ (stop_ℐ ℐ) x = (if x ∈ outs_ℐ ℐ then insert None (Some ` responses_ℐ ℐ x) else {})"
by transfer auto
lemma stop_ℐ_full [simp]: "stop_ℐ ℐ_full = ℐ_full"
by transfer(auto simp add: fun_eq_iff notin_range_Some)
lemma stop_ℐ_uniform [simp]:
"stop_ℐ (ℐ_uniform A B) = (if B = {} then ⊥ else ℐ_uniform A (insert None (Some ` B)))"
unfolding bot_ℐ_def by transfer(simp add: fun_eq_iff)
lifting_update ℐ.lifting
lifting_forget ℐ.lifting
end
lemma stop_ℐ_bot [simp]: "stop_ℐ ⊥ = ⊥"
by(simp only: bot_ℐ_def stop_ℐ_uniform)(simp)
lemma WT_gpv_stop [simp, WT_intro]: "stop_ℐ ℐ ⊢g gpv_stop gpv √" if "ℐ ⊢g gpv √"
using that by(coinduction arbitrary: gpv)(auto 4 3 dest: WT_gpvD)
lemma expectation_gpv_stop:
fixes fail and gpv :: "('a, 'b, 'c) gpv"
assumes WT: "ℐ ⊢g gpv √"
and fail: "fail ≤ c"
shows "expectation_gpv fail (stop_ℐ ℐ) (λ_. c) (gpv_stop gpv) = expectation_gpv fail ℐ (λ_. c) gpv" (is "?lhs = ?rhs")
proof(rule antisym)
show "expectation_gpv fail (stop_ℐ ℐ) (λ_. c) (gpv_stop gpv) ≤ expectation_gpv fail ℐ (λ_. c) gpv"
using WT
proof(induction arbitrary: gpv rule: parallel_fixp_induct_1_1[OF complete_lattice_partial_function_definitions complete_lattice_partial_function_definitions expectation_gpv.mono expectation_gpv.mono expectation_gpv_def expectation_gpv_def, case_names adm bottom step])
case adm show ?case by simp
case bottom show ?case by simp
case (step f g)
then show ?case
apply(simp add: pmf_map_spmf_None measure_spmf_return_spmf nn_integral_return)
apply(rule disjI2 nn_integral_mono_AE)+
apply(auto split!: generat.split simp add: image_image dest: WT_gpvD intro!: le_infI2 INF_mono)
done
qed
define stop :: "('a option, 'b, 'c option) gpv ⇒ _" where "stop = expectation_gpv fail (stop_ℐ ℐ) (λ_. c)"
show "?rhs ≤ stop (gpv_stop gpv)" using WT
proof(induction arbitrary: gpv rule: expectation_gpv_fixp_induct)
case adm show ?case by simp
case bottom show ?case by simp
case (step expectation_gpv')
have "expectation_gpv' gpv' ≤ c" if "ℐ ⊢g gpv' √" for gpv'
using expectation_gpv_const_le[of ℐ gpv' fail c] fail step.hyps(1)[of gpv'] that
by(simp add: max_def split: if_split_asm)
then show ?case using step unfolding stop_def
apply(subst expectation_gpv.simps)
apply(simp add: pmf_map_spmf_None)
apply(rule disjI2 nn_integral_mono_AE)+
apply(clarsimp split!: generat.split simp add: image_image)
subgoal by(auto 4 3 simp add: in_outs_ℐ_iff_responses_ℐ dest: WT_gpv_ContD intro: INF_lower2)
subgoal by(auto intro!: INF_mono rev_bexI dest: WT_gpvD)
done
qed
qed
lemma pgen_lossless_gpv_stop:
fixes fail and gpv :: "('a, 'b, 'c) gpv"
assumes WT: "ℐ ⊢g gpv √"
and fail: "fail ≤ 1"
shows "pgen_lossless_gpv fail (stop_ℐ ℐ) (gpv_stop gpv) = pgen_lossless_gpv fail ℐ gpv"
by(simp add: pgen_lossless_gpv_def expectation_gpv_stop assms)
lemma pfinite_gpv_stop [simp]:
"pfinite_gpv (stop_ℐ ℐ) (gpv_stop gpv) ⟷ pfinite_gpv ℐ gpv" if "ℐ ⊢g gpv √"
using that by(simp add: pgen_lossless_gpv_stop)
lemma plossless_gpv_stop [simp]:
"plossless_gpv (stop_ℐ ℐ) (gpv_stop gpv) ⟷ plossless_gpv ℐ gpv" if "ℐ ⊢g gpv √"
using that by(simp add: pgen_lossless_gpv_stop)
lemma results_gpv_stop_SomeD: "Some x ∈ results_gpv (stop_ℐ ℐ) (gpv_stop gpv) ⟹ x ∈ results_gpv ℐ gpv"
by(induction gpv'≡"gpv_stop gpv" arbitrary: gpv rule: results_gpv.induct)
(auto 4 3 intro: results_gpv.intros split: if_split_asm)
lemma Some_in_results'_gpv_gpv_stopD: "Some xy ∈ results'_gpv (gpv_stop gpv) ⟹ xy ∈ results'_gpv gpv"
unfolding results_gpv_ℐ_full[symmetric]
by(rule results_gpv_stop_SomeD) simp
subsection ‹term ‹exception_ℐ››