# HG changeset patch # User hoelzl # Date 1425981228 -3600 # Node ID 224741ede5ae1d604c82c0cdb8abb0df218c189c # Parent fb544855e3b14bbf66d2d63bbecdee0f153c90fa build pmf's on bind diff -r fb544855e3b1 -r 224741ede5ae src/HOL/Probability/Probability_Mass_Function.thy --- a/src/HOL/Probability/Probability_Mass_Function.thy Tue Mar 10 09:49:17 2015 +0100 +++ b/src/HOL/Probability/Probability_Mass_Function.thy Tue Mar 10 10:53:48 2015 +0100 @@ -12,6 +12,24 @@ "~~/src/HOL/Library/Multiset" begin +lemma AE_emeasure_singleton: + assumes x: "emeasure M {x} \ 0" and ae: "AE x in M. P x" shows "P x" +proof - + from x have x_M: "{x} \ sets M" + by (auto intro: emeasure_notin_sets) + from ae obtain N where N: "{x\space M. \ P x} \ N" "emeasure M N = 0" "N \ sets M" + by (auto elim: AE_E) + { assume "\ P x" + with x_M[THEN sets.sets_into_space] N have "emeasure M {x} \ emeasure M N" + by (intro emeasure_mono) auto + with x N have False + by (auto simp: emeasure_le_0_iff) } + then show "P x" by auto +qed + +lemma AE_measure_singleton: "measure M {x} \ 0 \ AE x in M. P x \ P x" + by (metis AE_emeasure_singleton measure_def emeasure_empty measure_empty) + lemma ereal_divide': "b \ 0 \ ereal (a / b) = ereal a / ereal b" using ereal_divide[of a b] by simp @@ -84,7 +102,7 @@ by (auto simp: emeasure_eq_measure) qed (auto intro!: exI[of _ "{x. measure M {x} \ 0}"] countable_support) -subsection {* PMF as measure *} +subsection \ PMF as measure \ typedef 'a pmf = "{M :: 'a measure. prob_space M \ sets M = UNIV \ (AE x in M. measure M {x} \ 0)}" morphisms measure_pmf Abs_pmf @@ -117,36 +135,8 @@ interpretation pmf_as_measure . -lift_definition pmf :: "'a pmf \ 'a \ real" is "\M x. measure M {x}" . - -lift_definition set_pmf :: "'a pmf \ 'a set" is "\M. {x. measure M {x} \ 0}" . - -lift_definition map_pmf :: "('a \ 'b) \ 'a pmf \ 'b pmf" is - "\f M. distr M (count_space UNIV) f" -proof safe - fix M and f :: "'a \ 'b" - let ?D = "distr M (count_space UNIV) f" - assume "prob_space M" and [simp]: "sets M = UNIV" and ae: "AE x in M. measure M {x} \ 0" - interpret prob_space M by fact - from ae have "AE x in M. measure M (f -` {f x}) \ 0" - proof eventually_elim - fix x - have "measure M {x} \ measure M (f -` {f x})" - by (intro finite_measure_mono) auto - then show "measure M {x} \ 0 \ measure M (f -` {f x}) \ 0" - using measure_nonneg[of M "{x}"] by auto - qed - then show "AE x in ?D. measure ?D {x} \ 0" - by (simp add: AE_distr_iff measure_distr measurable_def) -qed (auto simp: measurable_def prob_space.prob_space_distr) - -declare [[coercion set_pmf]] - -lemma countable_set_pmf [simp]: "countable (set_pmf p)" - by transfer (metis prob_space.finite_measure finite_measure.countable_support) - lemma sets_measure_pmf[simp]: "sets (measure_pmf p) = UNIV" - by transfer metis + by transfer blast lemma sets_measure_pmf_count_space[measurable_cong]: "sets (measure_pmf M) = sets (count_space UNIV)" @@ -164,19 +154,38 @@ lemma measurable_pmf_measure2[simp]: "measurable N (M :: 'a pmf) = measurable N (count_space UNIV)" by (intro measurable_cong_sets) simp_all -lemma pmf_positive: "x \ set_pmf p \ 0 < pmf p x" - by transfer (simp add: less_le measure_nonneg) +lemma measurable_pair_restrict_pmf2: + assumes "countable A" + assumes [measurable]: "\y. y \ A \ (\x. f (x, y)) \ measurable M L" + shows "f \ measurable (M \\<^sub>M restrict_space (measure_pmf N) A) L" (is "f \ measurable ?M _") +proof - + have [measurable_cong]: "sets (restrict_space (count_space UNIV) A) = sets (count_space A)" + by (simp add: restrict_count_space) -lemma pmf_nonneg: "0 \ pmf p x" - by transfer (simp add: measure_nonneg) + show ?thesis + by (intro measurable_compose_countable'[where f="\a b. f (fst b, a)" and g=snd and I=A, + unfolded pair_collapse] assms) + measurable +qed -lemma pmf_le_1: "pmf p x \ 1" - by (simp add: pmf.rep_eq) +lemma measurable_pair_restrict_pmf1: + assumes "countable A" + assumes [measurable]: "\x. x \ A \ (\y. f (x, y)) \ measurable N L" + shows "f \ measurable (restrict_space (measure_pmf M) A \\<^sub>M N) L" +proof - + have [measurable_cong]: "sets (restrict_space (count_space UNIV) A) = sets (count_space A)" + by (simp add: restrict_count_space) -lemma emeasure_pmf_single: - fixes M :: "'a pmf" - shows "emeasure M {x} = pmf M x" - by transfer (simp add: finite_measure.emeasure_eq_measure[OF prob_space.finite_measure]) + show ?thesis + by (intro measurable_compose_countable'[where f="\a b. f (a, snd b)" and g=fst and I=A, + unfolded pair_collapse] assms) + measurable +qed + +lift_definition pmf :: "'a pmf \ 'a \ real" is "\M x. measure M {x}" . + +lift_definition set_pmf :: "'a pmf \ 'a set" is "\M. {x. measure M {x} \ 0}" . +declare [[coercion set_pmf]] lemma AE_measure_pmf: "AE x in (M::'a pmf). x \ M" by transfer simp @@ -187,15 +196,20 @@ by transfer (simp add: finite_measure.emeasure_eq_measure[OF prob_space.finite_measure]) lemma AE_measure_pmf_iff: "(AE x in measure_pmf M. P x) \ (\y\M. P y)" -proof - - { fix y assume y: "y \ M" and P: "AE x in M. P x" "\ P y" - with P have "AE x in M. x \ y" - by auto - with y have False - by (simp add: emeasure_pmf_single_eq_zero_iff AE_iff_measurable[OF _ refl]) } - then show ?thesis - using AE_measure_pmf[of M] by auto -qed + using AE_measure_singleton[of M] AE_measure_pmf[of M] + by (auto simp: set_pmf.rep_eq) + +lemma countable_set_pmf [simp]: "countable (set_pmf p)" + by transfer (metis prob_space.finite_measure finite_measure.countable_support) + +lemma pmf_positive: "x \ set_pmf p \ 0 < pmf p x" + by transfer (simp add: less_le measure_nonneg) + +lemma pmf_nonneg: "0 \ pmf p x" + by transfer (simp add: measure_nonneg) + +lemma pmf_le_1: "pmf p x \ 1" + by (simp add: pmf.rep_eq) lemma set_pmf_not_empty: "set_pmf M \ {}" using AE_measure_pmf[of M] by (intro notI) simp @@ -203,6 +217,14 @@ lemma set_pmf_iff: "x \ set_pmf M \ pmf M x \ 0" by transfer simp +lemma set_pmf_eq: "set_pmf M = {x. pmf M x \ 0}" + by (auto simp: set_pmf_iff) + +lemma emeasure_pmf_single: + fixes M :: "'a pmf" + shows "emeasure M {x} = pmf M x" + by transfer (simp add: finite_measure.emeasure_eq_measure[OF prob_space.finite_measure]) + lemma emeasure_measure_pmf_finite: "finite S \ emeasure (measure_pmf M) S = (\s\S. pmf M s)" by (subst emeasure_eq_setsum_singleton) (auto simp: emeasure_pmf_single) @@ -290,6 +312,155 @@ using emeasure_eq_0_AE[where ?P="\x. x \ A" and M="measure_pmf p"] by(auto simp add: null_sets_def AE_measure_pmf_iff) +lemma measure_subprob: "measure_pmf M \ space (subprob_algebra (count_space UNIV))" + by (simp add: space_subprob_algebra subprob_space_measure_pmf) + +subsection \ Monad Interpretation \ + +lemma measurable_measure_pmf[measurable]: + "(\x. measure_pmf (M x)) \ measurable (count_space UNIV) (subprob_algebra (count_space UNIV))" + by (auto simp: space_subprob_algebra intro!: prob_space_imp_subprob_space) unfold_locales + +lemma bind_measure_pmf_cong: + assumes "\x. A x \ space (subprob_algebra N)" "\x. B x \ space (subprob_algebra N)" + assumes "\i. i \ set_pmf x \ A i = B i" + shows "bind (measure_pmf x) A = bind (measure_pmf x) B" +proof (rule measure_eqI) + show "sets (measure_pmf x \= A) = sets (measure_pmf x \= B)" + using assms by (subst (1 2) sets_bind) (auto simp: space_subprob_algebra) +next + fix X assume "X \ sets (measure_pmf x \= A)" + then have X: "X \ sets N" + using assms by (subst (asm) sets_bind) (auto simp: space_subprob_algebra) + show "emeasure (measure_pmf x \= A) X = emeasure (measure_pmf x \= B) X" + using assms + by (subst (1 2) emeasure_bind[where N=N, OF _ _ X]) + (auto intro!: nn_integral_cong_AE simp: AE_measure_pmf_iff) +qed + +lift_definition bind_pmf :: "'a pmf \ ('a \ 'b pmf ) \ 'b pmf" is bind +proof (clarify, intro conjI) + fix f :: "'a measure" and g :: "'a \ 'b measure" + assume "prob_space f" + then interpret f: prob_space f . + assume "sets f = UNIV" and ae_f: "AE x in f. measure f {x} \ 0" + then have s_f[simp]: "sets f = sets (count_space UNIV)" + by simp + assume g: "\x. prob_space (g x) \ sets (g x) = UNIV \ (AE y in g x. measure (g x) {y} \ 0)" + then have g: "\x. prob_space (g x)" and s_g[simp]: "\x. sets (g x) = sets (count_space UNIV)" + and ae_g: "\x. AE y in g x. measure (g x) {y} \ 0" + by auto + + have [measurable]: "g \ measurable f (subprob_algebra (count_space UNIV))" + by (auto simp: measurable_def space_subprob_algebra prob_space_imp_subprob_space g) + + show "prob_space (f \= g)" + using g by (intro f.prob_space_bind[where S="count_space UNIV"]) auto + then interpret fg: prob_space "f \= g" . + show [simp]: "sets (f \= g) = UNIV" + using sets_eq_imp_space_eq[OF s_f] + by (subst sets_bind[where N="count_space UNIV"]) auto + show "AE x in f \= g. measure (f \= g) {x} \ 0" + apply (simp add: fg.prob_eq_0 AE_bind[where B="count_space UNIV"]) + using ae_f + apply eventually_elim + using ae_g + apply eventually_elim + apply (auto dest: AE_measure_singleton) + done +qed + +lemma ereal_pmf_bind: "pmf (bind_pmf N f) i = (\\<^sup>+x. pmf (f x) i \measure_pmf N)" + unfolding pmf.rep_eq bind_pmf.rep_eq + by (auto simp: measure_pmf.measure_bind[where N="count_space UNIV"] measure_subprob measure_nonneg + intro!: nn_integral_eq_integral[symmetric] measure_pmf.integrable_const_bound[where B=1]) + +lemma pmf_bind: "pmf (bind_pmf N f) i = (\x. pmf (f x) i \measure_pmf N)" + using ereal_pmf_bind[of N f i] + by (subst (asm) nn_integral_eq_integral) + (auto simp: pmf_nonneg pmf_le_1 + intro!: nn_integral_eq_integral[symmetric] measure_pmf.integrable_const_bound[where B=1]) + +lemma bind_pmf_const[simp]: "bind_pmf M (\x. c) = c" + by transfer (simp add: bind_const' prob_space_imp_subprob_space) + +lemma set_bind_pmf: "set_pmf (bind_pmf M N) = (\M\set_pmf M. set_pmf (N M))" + unfolding set_pmf_eq ereal_eq_0(1)[symmetric] ereal_pmf_bind + by (auto simp add: nn_integral_0_iff_AE AE_measure_pmf_iff set_pmf_eq not_le less_le pmf_nonneg) + +lemma bind_pmf_cong: + assumes "p = q" + shows "(\x. x \ set_pmf q \ f x = g x) \ bind_pmf p f = bind_pmf q g" + unfolding `p = q`[symmetric] measure_pmf_inject[symmetric] bind_pmf.rep_eq + by (auto simp: AE_measure_pmf_iff Pi_iff space_subprob_algebra subprob_space_measure_pmf + sets_bind[where N="count_space UNIV"] emeasure_bind[where N="count_space UNIV"] + intro!: nn_integral_cong_AE measure_eqI) + +lemma bind_pmf_cong_simp: + "p = q \ (\x. x \ set_pmf q =simp=> f x = g x) \ bind_pmf p f = bind_pmf q g" + by (simp add: simp_implies_def cong: bind_pmf_cong) + +lemma measure_pmf_bind: "measure_pmf (bind_pmf M f) = (measure_pmf M \= (\x. measure_pmf (f x)))" + by transfer simp + +lemma nn_integral_bind_pmf[simp]: "(\\<^sup>+x. f x \bind_pmf M N) = (\\<^sup>+x. \\<^sup>+y. f y \N x \M)" + using measurable_measure_pmf[of N] + unfolding measure_pmf_bind + apply (subst (1 3) nn_integral_max_0[symmetric]) + apply (intro nn_integral_bind[where B="count_space UNIV"]) + apply auto + done + +lemma emeasure_bind_pmf[simp]: "emeasure (bind_pmf M N) X = (\\<^sup>+x. emeasure (N x) X \M)" + using measurable_measure_pmf[of N] + unfolding measure_pmf_bind + by (subst emeasure_bind[where N="count_space UNIV"]) auto + +lift_definition return_pmf :: "'a \ 'a pmf" is "return (count_space UNIV)" + by (auto intro!: prob_space_return simp: AE_return measure_return) + +lemma bind_return_pmf: "bind_pmf (return_pmf x) f = f x" + by transfer + (auto intro!: prob_space_imp_subprob_space bind_return[where N="count_space UNIV"] + simp: space_subprob_algebra) + +lemma set_return_pmf: "set_pmf (return_pmf x) = {x}" + by transfer (auto simp add: measure_return split: split_indicator) + +lemma bind_return_pmf': "bind_pmf N return_pmf = N" +proof (transfer, clarify) + fix N :: "'a measure" assume "sets N = UNIV" then show "N \= return (count_space UNIV) = N" + by (subst return_sets_cong[where N=N]) (simp_all add: bind_return') +qed + +lemma bind_assoc_pmf: "bind_pmf (bind_pmf A B) C = bind_pmf A (\x. bind_pmf (B x) C)" + by transfer + (auto intro!: bind_assoc[where N="count_space UNIV" and R="count_space UNIV"] + simp: measurable_def space_subprob_algebra prob_space_imp_subprob_space) + +definition "map_pmf f M = bind_pmf M (\x. return_pmf (f x))" + +lemma map_bind_pmf: "map_pmf f (bind_pmf M g) = bind_pmf M (\x. map_pmf f (g x))" + by (simp add: map_pmf_def bind_assoc_pmf) + +lemma bind_map_pmf: "bind_pmf (map_pmf f M) g = bind_pmf M (\x. g (f x))" + by (simp add: map_pmf_def bind_assoc_pmf bind_return_pmf) + +lemma map_pmf_transfer[transfer_rule]: + "rel_fun op = (rel_fun cr_pmf cr_pmf) (\f M. distr M (count_space UNIV) f) map_pmf" +proof - + have "rel_fun op = (rel_fun pmf_as_measure.cr_pmf pmf_as_measure.cr_pmf) + (\f M. M \= (return (count_space UNIV) o f)) map_pmf" + unfolding map_pmf_def[abs_def] comp_def by transfer_prover + then show ?thesis + by (force simp: rel_fun_def cr_pmf_def bind_return_distr) +qed + +lemma map_pmf_rep_eq: + "measure_pmf (map_pmf f M) = distr (measure_pmf M) (count_space UNIV) f" + unfolding map_pmf_def bind_pmf.rep_eq comp_def return_pmf.rep_eq + using bind_return_distr[of M f "count_space UNIV"] by (simp add: comp_def) + lemma map_pmf_id[simp]: "map_pmf id = id" by (rule, transfer) (auto simp: emeasure_distr measurable_def intro!: measure_eqI) @@ -302,20 +473,23 @@ lemma map_pmf_comp: "map_pmf f (map_pmf g M) = map_pmf (\x. f (g x)) M" using map_pmf_compose[of f g] by (simp add: comp_def) -lemma map_pmf_cong: - assumes "p = q" - shows "(\x. x \ set_pmf q \ f x = g x) \ map_pmf f p = map_pmf g q" - unfolding `p = q`[symmetric] measure_pmf_inject[symmetric] map_pmf.rep_eq - by (auto simp add: emeasure_distr AE_measure_pmf_iff intro!: emeasure_eq_AE measure_eqI) +lemma map_pmf_cong: "p = q \ (\x. x \ set_pmf q \ f x = g x) \ map_pmf f p = map_pmf g q" + unfolding map_pmf_def by (rule bind_pmf_cong) auto + +lemma pmf_set_map: "set_pmf \ map_pmf f = op ` f \ set_pmf" + by (auto simp add: comp_def fun_eq_iff map_pmf_def set_bind_pmf set_return_pmf) + +lemma set_map_pmf: "set_pmf (map_pmf f M) = f`set_pmf M" + using pmf_set_map[of f] by (auto simp: comp_def fun_eq_iff) lemma emeasure_map_pmf[simp]: "emeasure (map_pmf f M) X = emeasure M (f -` X)" - unfolding map_pmf.rep_eq by (subst emeasure_distr) auto + unfolding map_pmf_rep_eq by (subst emeasure_distr) auto lemma nn_integral_map_pmf[simp]: "(\\<^sup>+x. f x \map_pmf g M) = (\\<^sup>+x. f (g x) \M)" - unfolding map_pmf.rep_eq by (intro nn_integral_distr) auto + unfolding map_pmf_rep_eq by (intro nn_integral_distr) auto lemma ereal_pmf_map: "pmf (map_pmf f p) x = (\\<^sup>+ y. indicator (f -` {x}) y \measure_pmf p)" -proof(transfer fixing: f x) +proof (transfer fixing: f x) fix p :: "'b measure" presume "prob_space p" then interpret prob_space p . @@ -324,36 +498,6 @@ by(simp add: measure_distr measurable_def emeasure_eq_measure) qed simp_all -lemma pmf_set_map: - fixes f :: "'a \ 'b" - shows "set_pmf \ map_pmf f = op ` f \ set_pmf" -proof (rule, transfer, clarsimp simp add: measure_distr measurable_def) - fix f :: "'a \ 'b" and M :: "'a measure" - assume "prob_space M" and ae: "AE x in M. measure M {x} \ 0" and [simp]: "sets M = UNIV" - interpret prob_space M by fact - show "{x. measure M (f -` {x}) \ 0} = f ` {x. measure M {x} \ 0}" - proof safe - fix x assume "measure M (f -` {x}) \ 0" - moreover have "measure M (f -` {x}) = measure M {y. f y = x \ measure M {y} \ 0}" - using ae by (intro finite_measure_eq_AE) auto - ultimately have "{y. f y = x \ measure M {y} \ 0} \ {}" - by (metis measure_empty) - then show "x \ f ` {x. measure M {x} \ 0}" - by auto - next - fix x assume "measure M {x} \ 0" - then have "0 < measure M {x}" - using measure_nonneg[of M "{x}"] by auto - also have "measure M {x} \ measure M (f -` {f x})" - by (intro finite_measure_mono) auto - finally show "measure M (f -` {f x}) = 0 \ False" - by simp - qed -qed - -lemma set_map_pmf: "set_pmf (map_pmf f M) = f`set_pmf M" - using pmf_set_map[of f] by (auto simp: comp_def fun_eq_iff) - lemma nn_integral_pmf: "(\\<^sup>+ x. pmf p x \count_space A) = emeasure (measure_pmf p) A" proof - have "(\\<^sup>+ x. pmf p x \count_space A) = (\\<^sup>+ x. pmf p x \count_space (A \ set_pmf p))" @@ -367,7 +511,109 @@ finally show ?thesis . qed -subsection {* PMFs as function *} +lemma map_return_pmf: "map_pmf f (return_pmf x) = return_pmf (f x)" + by transfer (simp add: distr_return) + +lemma map_pmf_const[simp]: "map_pmf (\_. c) M = return_pmf c" + by transfer (auto simp: prob_space.distr_const) + +lemma pmf_return: "pmf (return_pmf x) y = indicator {y} x" + by transfer (simp add: measure_return) + +lemma nn_integral_return_pmf[simp]: "0 \ f x \ (\\<^sup>+x. f x \return_pmf x) = f x" + unfolding return_pmf.rep_eq by (intro nn_integral_return) auto + +lemma emeasure_return_pmf[simp]: "emeasure (return_pmf x) X = indicator X x" + unfolding return_pmf.rep_eq by (intro emeasure_return) auto + +lemma return_pmf_inj[simp]: "return_pmf x = return_pmf y \ x = y" + by (metis insertI1 set_return_pmf singletonD) + +definition "pair_pmf A B = bind_pmf A (\x. bind_pmf B (\y. return_pmf (x, y)))" + +lemma pmf_pair: "pmf (pair_pmf M N) (a, b) = pmf M a * pmf N b" + unfolding pair_pmf_def pmf_bind pmf_return + apply (subst integral_measure_pmf[where A="{b}"]) + apply (auto simp: indicator_eq_0_iff) + apply (subst integral_measure_pmf[where A="{a}"]) + apply (auto simp: indicator_eq_0_iff setsum_nonneg_eq_0_iff pmf_nonneg) + done + +lemma set_pair_pmf: "set_pmf (pair_pmf A B) = set_pmf A \ set_pmf B" + unfolding pair_pmf_def set_bind_pmf set_return_pmf by auto + +lemma measure_pmf_in_subprob_space[measurable (raw)]: + "measure_pmf M \ space (subprob_algebra (count_space UNIV))" + by (simp add: space_subprob_algebra) intro_locales + +lemma nn_integral_pair_pmf': "(\\<^sup>+x. f x \pair_pmf A B) = (\\<^sup>+a. \\<^sup>+b. f (a, b) \B \A)" +proof - + have "(\\<^sup>+x. f x \pair_pmf A B) = (\\<^sup>+x. max 0 (f x) * indicator (A \ B) x \pair_pmf A B)" + by (subst nn_integral_max_0[symmetric]) + (auto simp: AE_measure_pmf_iff set_pair_pmf intro!: nn_integral_cong_AE) + also have "\ = (\\<^sup>+a. \\<^sup>+b. max 0 (f (a, b)) * indicator (A \ B) (a, b) \B \A)" + by (simp add: pair_pmf_def) + also have "\ = (\\<^sup>+a. \\<^sup>+b. max 0 (f (a, b)) \B \A)" + by (auto intro!: nn_integral_cong_AE simp: AE_measure_pmf_iff) + finally show ?thesis + unfolding nn_integral_max_0 . +qed + +lemma bind_pair_pmf: + assumes M[measurable]: "M \ measurable (count_space UNIV \\<^sub>M count_space UNIV) (subprob_algebra N)" + shows "measure_pmf (pair_pmf A B) \= M = (measure_pmf A \= (\x. measure_pmf B \= (\y. M (x, y))))" + (is "?L = ?R") +proof (rule measure_eqI) + have M'[measurable]: "M \ measurable (pair_pmf A B) (subprob_algebra N)" + using M[THEN measurable_space] by (simp_all add: space_pair_measure) + + note measurable_bind[where N="count_space UNIV", measurable] + note measure_pmf_in_subprob_space[simp] + + have sets_eq_N: "sets ?L = N" + by (subst sets_bind[OF sets_kernel[OF M']]) auto + show "sets ?L = sets ?R" + using measurable_space[OF M] + by (simp add: sets_eq_N space_pair_measure space_subprob_algebra) + fix X assume "X \ sets ?L" + then have X[measurable]: "X \ sets N" + unfolding sets_eq_N . + then show "emeasure ?L X = emeasure ?R X" + apply (simp add: emeasure_bind[OF _ M' X]) + apply (simp add: nn_integral_bind[where B="count_space UNIV"] pair_pmf_def measure_pmf_bind[of A] + nn_integral_measure_pmf_finite set_return_pmf emeasure_nonneg pmf_return one_ereal_def[symmetric]) + apply (subst emeasure_bind[OF _ _ X]) + apply measurable + apply (subst emeasure_bind[OF _ _ X]) + apply measurable + done +qed + +lemma map_fst_pair_pmf: "map_pmf fst (pair_pmf A B) = A" + by (simp add: pair_pmf_def map_pmf_def bind_assoc_pmf bind_return_pmf bind_return_pmf') + +lemma map_snd_pair_pmf: "map_pmf snd (pair_pmf A B) = B" + by (simp add: pair_pmf_def map_pmf_def bind_assoc_pmf bind_return_pmf bind_return_pmf') + +lemma nn_integral_pmf': + "inj_on f A \ (\\<^sup>+x. pmf p (f x) \count_space A) = emeasure p (f ` A)" + by (subst nn_integral_bij_count_space[where g=f and B="f`A"]) + (auto simp: bij_betw_def nn_integral_pmf) + +lemma pmf_le_0_iff[simp]: "pmf M p \ 0 \ pmf M p = 0" + using pmf_nonneg[of M p] by simp + +lemma min_pmf_0[simp]: "min (pmf M p) 0 = 0" "min 0 (pmf M p) = 0" + using pmf_nonneg[of M p] by simp_all + +lemma pmf_eq_0_set_pmf: "pmf M p = 0 \ p \ set_pmf M" + unfolding set_pmf_iff by simp + +lemma pmf_map_inj: "inj_on f (set_pmf M) \ x \ set_pmf M \ pmf (map_pmf f M) (f x) = pmf M x" + by (auto simp: pmf.rep_eq map_pmf_rep_eq measure_distr AE_measure_pmf_iff inj_onD + intro!: measure_pmf.finite_measure_eq_AE) + +subsection \ PMFs as function \ context fixes f :: "'a \ real" @@ -468,8 +714,484 @@ lemma pmf_eq_iff: "M = N \ (\i. pmf M i = pmf N i)" by (auto intro: pmf_eqI) +lemma bind_commute_pmf: "bind_pmf A (\x. bind_pmf B (C x)) = bind_pmf B (\y. bind_pmf A (\x. C x y))" + unfolding pmf_eq_iff pmf_bind +proof + fix i + interpret B: prob_space "restrict_space B B" + by (intro prob_space_restrict_space measure_pmf.emeasure_eq_1_AE) + (auto simp: AE_measure_pmf_iff) + interpret A: prob_space "restrict_space A A" + by (intro prob_space_restrict_space measure_pmf.emeasure_eq_1_AE) + (auto simp: AE_measure_pmf_iff) + + interpret AB: pair_prob_space "restrict_space A A" "restrict_space B B" + by unfold_locales + + have "(\ x. \ y. pmf (C x y) i \B \A) = (\ x. (\ y. pmf (C x y) i \restrict_space B B) \A)" + by (rule integral_cong) (auto intro!: integral_pmf_restrict) + also have "\ = (\ x. (\ y. pmf (C x y) i \restrict_space B B) \restrict_space A A)" + by (intro integral_pmf_restrict B.borel_measurable_lebesgue_integral measurable_pair_restrict_pmf2 + countable_set_pmf borel_measurable_count_space) + also have "\ = (\ y. \ x. pmf (C x y) i \restrict_space A A \restrict_space B B)" + by (rule AB.Fubini_integral[symmetric]) + (auto intro!: AB.integrable_const_bound[where B=1] measurable_pair_restrict_pmf2 + simp: pmf_nonneg pmf_le_1 measurable_restrict_space1) + also have "\ = (\ y. \ x. pmf (C x y) i \restrict_space A A \B)" + by (intro integral_pmf_restrict[symmetric] A.borel_measurable_lebesgue_integral measurable_pair_restrict_pmf2 + countable_set_pmf borel_measurable_count_space) + also have "\ = (\ y. \ x. pmf (C x y) i \A \B)" + by (rule integral_cong) (auto intro!: integral_pmf_restrict[symmetric]) + finally show "(\ x. \ y. pmf (C x y) i \B \A) = (\ y. \ x. pmf (C x y) i \A \B)" . +qed + +lemma pair_map_pmf1: "pair_pmf (map_pmf f A) B = map_pmf (apfst f) (pair_pmf A B)" +proof (safe intro!: pmf_eqI) + fix a :: "'a" and b :: "'b" + have [simp]: "\c d. indicator (apfst f -` {(a, b)}) (c, d) = indicator (f -` {a}) c * (indicator {b} d::ereal)" + by (auto split: split_indicator) + + have "ereal (pmf (pair_pmf (map_pmf f A) B) (a, b)) = + ereal (pmf (map_pmf (apfst f) (pair_pmf A B)) (a, b))" + unfolding pmf_pair ereal_pmf_map + by (simp add: nn_integral_pair_pmf' max_def emeasure_pmf_single nn_integral_multc pmf_nonneg + emeasure_map_pmf[symmetric] del: emeasure_map_pmf) + then show "pmf (pair_pmf (map_pmf f A) B) (a, b) = pmf (map_pmf (apfst f) (pair_pmf A B)) (a, b)" + by simp +qed + +lemma pair_map_pmf2: "pair_pmf A (map_pmf f B) = map_pmf (apsnd f) (pair_pmf A B)" +proof (safe intro!: pmf_eqI) + fix a :: "'a" and b :: "'b" + have [simp]: "\c d. indicator (apsnd f -` {(a, b)}) (c, d) = indicator {a} c * (indicator (f -` {b}) d::ereal)" + by (auto split: split_indicator) + + have "ereal (pmf (pair_pmf A (map_pmf f B)) (a, b)) = + ereal (pmf (map_pmf (apsnd f) (pair_pmf A B)) (a, b))" + unfolding pmf_pair ereal_pmf_map + by (simp add: nn_integral_pair_pmf' max_def emeasure_pmf_single nn_integral_cmult nn_integral_multc pmf_nonneg + emeasure_map_pmf[symmetric] del: emeasure_map_pmf) + then show "pmf (pair_pmf A (map_pmf f B)) (a, b) = pmf (map_pmf (apsnd f) (pair_pmf A B)) (a, b)" + by simp +qed + +lemma map_pair: "map_pmf (\(a, b). (f a, g b)) (pair_pmf A B) = pair_pmf (map_pmf f A) (map_pmf g B)" + by (simp add: pair_map_pmf2 pair_map_pmf1 map_pmf_comp split_beta') + end +subsection \ Conditional Probabilities \ + +context + fixes p :: "'a pmf" and s :: "'a set" + assumes not_empty: "set_pmf p \ s \ {}" +begin + +interpretation pmf_as_measure . + +lemma emeasure_measure_pmf_not_zero: "emeasure (measure_pmf p) s \ 0" +proof + assume "emeasure (measure_pmf p) s = 0" + then have "AE x in measure_pmf p. x \ s" + by (rule AE_I[rotated]) auto + with not_empty show False + by (auto simp: AE_measure_pmf_iff) +qed + +lemma measure_measure_pmf_not_zero: "measure (measure_pmf p) s \ 0" + using emeasure_measure_pmf_not_zero unfolding measure_pmf.emeasure_eq_measure by simp + +lift_definition cond_pmf :: "'a pmf" is + "uniform_measure (measure_pmf p) s" +proof (intro conjI) + show "prob_space (uniform_measure (measure_pmf p) s)" + by (intro prob_space_uniform_measure) (auto simp: emeasure_measure_pmf_not_zero) + show "AE x in uniform_measure (measure_pmf p) s. measure (uniform_measure (measure_pmf p) s) {x} \ 0" + by (simp add: emeasure_measure_pmf_not_zero measure_measure_pmf_not_zero AE_uniform_measure + AE_measure_pmf_iff set_pmf.rep_eq) +qed simp + +lemma pmf_cond: "pmf cond_pmf x = (if x \ s then pmf p x / measure p s else 0)" + by transfer (simp add: emeasure_measure_pmf_not_zero pmf.rep_eq) + +lemma set_cond_pmf: "set_pmf cond_pmf = set_pmf p \ s" + by (auto simp add: set_pmf_iff pmf_cond measure_measure_pmf_not_zero split: split_if_asm) + +end + +lemma cond_map_pmf: + assumes "set_pmf p \ f -` s \ {}" + shows "cond_pmf (map_pmf f p) s = map_pmf f (cond_pmf p (f -` s))" +proof - + have *: "set_pmf (map_pmf f p) \ s \ {}" + using assms by (simp add: set_map_pmf) auto + { fix x + have "ereal (pmf (map_pmf f (cond_pmf p (f -` s))) x) = + emeasure p (f -` s \ f -` {x}) / emeasure p (f -` s)" + unfolding ereal_pmf_map cond_pmf.rep_eq[OF assms] by (simp add: nn_integral_uniform_measure) + also have "f -` s \ f -` {x} = (if x \ s then f -` {x} else {})" + by auto + also have "emeasure p (if x \ s then f -` {x} else {}) / emeasure p (f -` s) = + ereal (pmf (cond_pmf (map_pmf f p) s) x)" + using measure_measure_pmf_not_zero[OF *] + by (simp add: pmf_cond[OF *] ereal_divide' ereal_pmf_map measure_pmf.emeasure_eq_measure[symmetric] + del: ereal_divide) + finally have "ereal (pmf (cond_pmf (map_pmf f p) s) x) = ereal (pmf (map_pmf f (cond_pmf p (f -` s))) x)" + by simp } + then show ?thesis + by (intro pmf_eqI) simp +qed + +lemma bind_cond_pmf_cancel: + assumes in_S: "\x. x \ set_pmf p \ x \ S x" "\x. x \ set_pmf q \ x \ S x" + assumes S_eq: "\x y. x \ S y \ S x = S y" + and same: "\x. measure (measure_pmf p) (S x) = measure (measure_pmf q) (S x)" + shows "bind_pmf p (\x. cond_pmf q (S x)) = q" (is "?lhs = _") +proof (rule pmf_eqI) + { fix x + assume "x \ set_pmf p" + hence "set_pmf p \ (S x) \ {}" using in_S by auto + hence "measure (measure_pmf p) (S x) \ 0" + by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff) + with same have "measure (measure_pmf q) (S x) \ 0" by simp + hence "set_pmf q \ S x \ {}" + by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff) } + note [simp] = this + + fix z + have pmf_q_z: "z \ S z \ pmf q z = 0" + by(erule contrapos_np)(simp add: pmf_eq_0_set_pmf in_S) + + have "ereal (pmf ?lhs z) = \\<^sup>+ x. ereal (pmf (cond_pmf q (S x)) z) \measure_pmf p" + by(simp add: ereal_pmf_bind) + also have "\ = \\<^sup>+ x. ereal (pmf q z / measure p (S z)) * indicator (S z) x \measure_pmf p" + by(rule nn_integral_cong_AE)(auto simp add: AE_measure_pmf_iff pmf_cond same pmf_q_z in_S dest!: S_eq split: split_indicator) + also have "\ = pmf q z" using pmf_nonneg[of q z] + by (subst nn_integral_cmult)(auto simp add: measure_nonneg measure_pmf.emeasure_eq_measure same measure_pmf.prob_eq_0 AE_measure_pmf_iff pmf_eq_0_set_pmf in_S) + finally show "pmf ?lhs z = pmf q z" by simp +qed + +subsection \ Relator \ + +inductive rel_pmf :: "('a \ 'b \ bool) \ 'a pmf \ 'b pmf \ bool" +for R p q +where + "\ \x y. (x, y) \ set_pmf pq \ R x y; + map_pmf fst pq = p; map_pmf snd pq = q \ + \ rel_pmf R p q" + +bnf pmf: "'a pmf" map: map_pmf sets: set_pmf bd : "natLeq" rel: rel_pmf +proof - + show "map_pmf id = id" by (rule map_pmf_id) + show "\f g. map_pmf (f \ g) = map_pmf f \ map_pmf g" by (rule map_pmf_compose) + show "\f g::'a \ 'b. \p. (\x. x \ set_pmf p \ f x = g x) \ map_pmf f p = map_pmf g p" + by (intro map_pmf_cong refl) + + show "\f::'a \ 'b. set_pmf \ map_pmf f = op ` f \ set_pmf" + by (rule pmf_set_map) + + { fix p :: "'s pmf" + have "(card_of (set_pmf p), card_of (UNIV :: nat set)) \ ordLeq" + by (rule card_of_ordLeqI[where f="to_nat_on (set_pmf p)"]) + (auto intro: countable_set_pmf) + also have "(card_of (UNIV :: nat set), natLeq) \ ordLeq" + by (metis Field_natLeq card_of_least natLeq_Well_order) + finally show "(card_of (set_pmf p), natLeq) \ ordLeq" . } + + show "\R. rel_pmf R = + (BNF_Def.Grp {x. set_pmf x \ {(x, y). R x y}} (map_pmf fst))\\ OO + BNF_Def.Grp {x. set_pmf x \ {(x, y). R x y}} (map_pmf snd)" + by (auto simp add: fun_eq_iff BNF_Def.Grp_def OO_def rel_pmf.simps) + + { fix p :: "'a pmf" and f :: "'a \ 'b" and g x + assume p: "\z. z \ set_pmf p \ f z = g z" + and x: "x \ set_pmf p" + thus "f x = g x" by simp } + + fix R :: "'a => 'b \ bool" and S :: "'b \ 'c \ bool" + { fix p q r + assume pq: "rel_pmf R p q" + and qr:"rel_pmf S q r" + from pq obtain pq where pq: "\x y. (x, y) \ set_pmf pq \ R x y" + and p: "p = map_pmf fst pq" and q: "q = map_pmf snd pq" by cases auto + from qr obtain qr where qr: "\y z. (y, z) \ set_pmf qr \ S y z" + and q': "q = map_pmf fst qr" and r: "r = map_pmf snd qr" by cases auto + + def pr \ "bind_pmf pq (\(x, y). bind_pmf (cond_pmf qr {(y', z). y' = y}) (\(y', z). return_pmf (x, z)))" + have pr_welldefined: "\y. y \ q \ qr \ {(y', z). y' = y} \ {}" + by (force simp: q' set_map_pmf) + + have "rel_pmf (R OO S) p r" + proof (rule rel_pmf.intros) + fix x z assume "(x, z) \ pr" + then have "\y. (x, y) \ pq \ (y, z) \ qr" + by (auto simp: q pr_welldefined pr_def set_bind_pmf split_beta set_return_pmf set_cond_pmf set_map_pmf) + with pq qr show "(R OO S) x z" + by blast + next + have "map_pmf snd pr = map_pmf snd (bind_pmf q (\y. cond_pmf qr {(y', z). y' = y}))" + by (simp add: pr_def q split_beta bind_map_pmf map_pmf_def[symmetric] map_bind_pmf map_return_pmf) + then show "map_pmf snd pr = r" + unfolding r q' bind_map_pmf by (subst (asm) bind_cond_pmf_cancel) auto + qed (simp add: pr_def map_bind_pmf split_beta map_return_pmf map_pmf_def[symmetric] p) } + then show "rel_pmf R OO rel_pmf S \ rel_pmf (R OO S)" + by(auto simp add: le_fun_def) +qed (fact natLeq_card_order natLeq_cinfinite)+ + +lemma rel_pmf_return_pmf1: "rel_pmf R (return_pmf x) M \ (\a\M. R x a)" +proof safe + fix a assume "a \ M" "rel_pmf R (return_pmf x) M" + then obtain pq where *: "\a b. (a, b) \ set_pmf pq \ R a b" + and eq: "return_pmf x = map_pmf fst pq" "M = map_pmf snd pq" + by (force elim: rel_pmf.cases) + moreover have "set_pmf (return_pmf x) = {x}" + by (simp add: set_return_pmf) + with `a \ M` have "(x, a) \ pq" + by (force simp: eq set_map_pmf) + with * show "R x a" + by auto +qed (auto intro!: rel_pmf.intros[where pq="pair_pmf (return_pmf x) M"] + simp: map_fst_pair_pmf map_snd_pair_pmf set_pair_pmf set_return_pmf) + +lemma rel_pmf_return_pmf2: "rel_pmf R M (return_pmf x) \ (\a\M. R a x)" + by (subst pmf.rel_flip[symmetric]) (simp add: rel_pmf_return_pmf1) + +lemma rel_return_pmf[simp]: "rel_pmf R (return_pmf x1) (return_pmf x2) = R x1 x2" + unfolding rel_pmf_return_pmf2 set_return_pmf by simp + +lemma rel_pmf_False[simp]: "rel_pmf (\x y. False) x y = False" + unfolding pmf.in_rel fun_eq_iff using set_pmf_not_empty by fastforce + +lemma rel_pmf_rel_prod: + "rel_pmf (rel_prod R S) (pair_pmf A A') (pair_pmf B B') \ rel_pmf R A B \ rel_pmf S A' B'" +proof safe + assume "rel_pmf (rel_prod R S) (pair_pmf A A') (pair_pmf B B')" + then obtain pq where pq: "\a b c d. ((a, c), (b, d)) \ set_pmf pq \ R a b \ S c d" + and eq: "map_pmf fst pq = pair_pmf A A'" "map_pmf snd pq = pair_pmf B B'" + by (force elim: rel_pmf.cases) + show "rel_pmf R A B" + proof (rule rel_pmf.intros) + let ?f = "\(a, b). (fst a, fst b)" + have [simp]: "(\x. fst (?f x)) = fst o fst" "(\x. snd (?f x)) = fst o snd" + by auto + + show "map_pmf fst (map_pmf ?f pq) = A" + by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_fst_pair_pmf) + show "map_pmf snd (map_pmf ?f pq) = B" + by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_fst_pair_pmf) + + fix a b assume "(a, b) \ set_pmf (map_pmf ?f pq)" + then obtain c d where "((a, c), (b, d)) \ set_pmf pq" + by (auto simp: set_map_pmf) + from pq[OF this] show "R a b" .. + qed + show "rel_pmf S A' B'" + proof (rule rel_pmf.intros) + let ?f = "\(a, b). (snd a, snd b)" + have [simp]: "(\x. fst (?f x)) = snd o fst" "(\x. snd (?f x)) = snd o snd" + by auto + + show "map_pmf fst (map_pmf ?f pq) = A'" + by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_snd_pair_pmf) + show "map_pmf snd (map_pmf ?f pq) = B'" + by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_snd_pair_pmf) + + fix c d assume "(c, d) \ set_pmf (map_pmf ?f pq)" + then obtain a b where "((a, c), (b, d)) \ set_pmf pq" + by (auto simp: set_map_pmf) + from pq[OF this] show "S c d" .. + qed +next + assume "rel_pmf R A B" "rel_pmf S A' B'" + then obtain Rpq Spq + where Rpq: "\a b. (a, b) \ set_pmf Rpq \ R a b" + "map_pmf fst Rpq = A" "map_pmf snd Rpq = B" + and Spq: "\a b. (a, b) \ set_pmf Spq \ S a b" + "map_pmf fst Spq = A'" "map_pmf snd Spq = B'" + by (force elim: rel_pmf.cases) + + let ?f = "(\((a, c), (b, d)). ((a, b), (c, d)))" + let ?pq = "map_pmf ?f (pair_pmf Rpq Spq)" + have [simp]: "(\x. fst (?f x)) = (\(a, b). (fst a, fst b))" "(\x. snd (?f x)) = (\(a, b). (snd a, snd b))" + by auto + + show "rel_pmf (rel_prod R S) (pair_pmf A A') (pair_pmf B B')" + by (rule rel_pmf.intros[where pq="?pq"]) + (auto simp: map_snd_pair_pmf map_fst_pair_pmf set_pair_pmf set_map_pmf map_pmf_comp Rpq Spq + map_pair) +qed + +lemma rel_pmf_reflI: + assumes "\x. x \ set_pmf p \ P x x" + shows "rel_pmf P p p" +by(rule rel_pmf.intros[where pq="map_pmf (\x. (x, x)) p"])(auto simp add: pmf.map_comp o_def set_map_pmf assms) + +context +begin + +interpretation pmf_as_measure . + +definition "join_pmf M = bind_pmf M (\x. x)" + +lemma bind_eq_join_pmf: "bind_pmf M f = join_pmf (map_pmf f M)" + unfolding join_pmf_def bind_map_pmf .. + +lemma join_eq_bind_pmf: "join_pmf M = bind_pmf M id" + by (simp add: join_pmf_def id_def) + +lemma pmf_join: "pmf (join_pmf N) i = (\M. pmf M i \measure_pmf N)" + unfolding join_pmf_def pmf_bind .. + +lemma ereal_pmf_join: "ereal (pmf (join_pmf N) i) = (\\<^sup>+M. pmf M i \measure_pmf N)" + unfolding join_pmf_def ereal_pmf_bind .. + +lemma set_pmf_join_pmf: "set_pmf (join_pmf f) = (\p\set_pmf f. set_pmf p)" + by (simp add: join_pmf_def set_bind_pmf) + +lemma join_return_pmf: "join_pmf (return_pmf M) = M" + by (simp add: integral_return pmf_eq_iff pmf_join return_pmf.rep_eq) + +lemma map_join_pmf: "map_pmf f (join_pmf AA) = join_pmf (map_pmf (map_pmf f) AA)" + by (simp add: join_pmf_def map_pmf_def bind_assoc_pmf bind_return_pmf) + +lemma join_map_return_pmf: "join_pmf (map_pmf return_pmf A) = A" + by (simp add: join_pmf_def map_pmf_def bind_assoc_pmf bind_return_pmf bind_return_pmf') + +end + +lemma rel_pmf_joinI: + assumes "rel_pmf (rel_pmf P) p q" + shows "rel_pmf P (join_pmf p) (join_pmf q)" +proof - + from assms obtain pq where p: "p = map_pmf fst pq" + and q: "q = map_pmf snd pq" + and P: "\x y. (x, y) \ set_pmf pq \ rel_pmf P x y" + by cases auto + from P obtain PQ + where PQ: "\x y a b. \ (x, y) \ set_pmf pq; (a, b) \ set_pmf (PQ x y) \ \ P a b" + and x: "\x y. (x, y) \ set_pmf pq \ map_pmf fst (PQ x y) = x" + and y: "\x y. (x, y) \ set_pmf pq \ map_pmf snd (PQ x y) = y" + by(metis rel_pmf.simps) + + let ?r = "bind_pmf pq (\(x, y). PQ x y)" + have "\a b. (a, b) \ set_pmf ?r \ P a b" by(auto simp add: set_bind_pmf intro: PQ) + moreover have "map_pmf fst ?r = join_pmf p" "map_pmf snd ?r = join_pmf q" + by (simp_all add: p q x y join_pmf_def map_bind_pmf bind_map_pmf split_def cong: bind_pmf_cong) + ultimately show ?thesis .. +qed + +lemma rel_pmf_bindI: + assumes pq: "rel_pmf R p q" + and fg: "\x y. R x y \ rel_pmf P (f x) (g y)" + shows "rel_pmf P (bind_pmf p f) (bind_pmf q g)" + unfolding bind_eq_join_pmf + by (rule rel_pmf_joinI) + (auto simp add: pmf.rel_map intro: pmf.rel_mono[THEN le_funD, THEN le_funD, THEN le_boolD, THEN mp, OF _ pq] fg) + +text {* + Proof that @{const rel_pmf} preserves orders. + Antisymmetry proof follows Thm. 1 in N. Saheb-Djahromi, Cpo's of measures for nondeterminism, + Theoretical Computer Science 12(1):19--37, 1980, + @{url "http://dx.doi.org/10.1016/0304-3975(80)90003-1"} +*} + +lemma + assumes *: "rel_pmf R p q" + and refl: "reflp R" and trans: "transp R" + shows measure_Ici: "measure p {y. R x y} \ measure q {y. R x y}" (is ?thesis1) + and measure_Ioi: "measure p {y. R x y \ \ R y x} \ measure q {y. R x y \ \ R y x}" (is ?thesis2) +proof - + from * obtain pq + where pq: "\x y. (x, y) \ set_pmf pq \ R x y" + and p: "p = map_pmf fst pq" + and q: "q = map_pmf snd pq" + by cases auto + show ?thesis1 ?thesis2 unfolding p q map_pmf_rep_eq using refl trans + by(auto 4 3 simp add: measure_distr reflpD AE_measure_pmf_iff intro!: measure_pmf.finite_measure_mono_AE dest!: pq elim: transpE) +qed + +lemma rel_pmf_inf: + fixes p q :: "'a pmf" + assumes 1: "rel_pmf R p q" + assumes 2: "rel_pmf R q p" + and refl: "reflp R" and trans: "transp R" + shows "rel_pmf (inf R R\\) p q" +proof + let ?E = "\x. {y. R x y \ R y x}" + let ?\E = "\x. measure q (?E x)" + { fix x + have "measure p (?E x) = measure p ({y. R x y} - {y. R x y \ \ R y x})" + by(auto intro!: arg_cong[where f="measure p"]) + also have "\ = measure p {y. R x y} - measure p {y. R x y \ \ R y x}" + by (rule measure_pmf.finite_measure_Diff) auto + also have "measure p {y. R x y \ \ R y x} = measure q {y. R x y \ \ R y x}" + using 1 2 refl trans by(auto intro!: Orderings.antisym measure_Ioi) + also have "measure p {y. R x y} = measure q {y. R x y}" + using 1 2 refl trans by(auto intro!: Orderings.antisym measure_Ici) + also have "measure q {y. R x y} - measure q {y. R x y \ ~ R y x} = + measure q ({y. R x y} - {y. R x y \ \ R y x})" + by(rule measure_pmf.finite_measure_Diff[symmetric]) auto + also have "\ = ?\E x" + by(auto intro!: arg_cong[where f="measure q"]) + also note calculation } + note eq = this + + def pq \ "bind_pmf p (\x. bind_pmf (cond_pmf q (?E x)) (\y. return_pmf (x, y)))" + + show "map_pmf fst pq = p" + by(simp add: pq_def map_bind_pmf map_return_pmf bind_return_pmf') + + show "map_pmf snd pq = q" + unfolding pq_def map_bind_pmf map_return_pmf bind_return_pmf' snd_conv + by(subst bind_cond_pmf_cancel)(auto simp add: reflpD[OF \reflp R\] eq intro: transpD[OF \transp R\]) + + fix x y + assume "(x, y) \ set_pmf pq" + moreover + { assume "x \ set_pmf p" + hence "measure (measure_pmf p) (?E x) \ 0" + by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff intro: reflpD[OF \reflp R\]) + hence "measure (measure_pmf q) (?E x) \ 0" using eq by simp + hence "set_pmf q \ {y. R x y \ R y x} \ {}" + by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff) } + ultimately show "inf R R\\ x y" + by(auto simp add: pq_def set_bind_pmf set_return_pmf set_cond_pmf) +qed + +lemma rel_pmf_antisym: + fixes p q :: "'a pmf" + assumes 1: "rel_pmf R p q" + assumes 2: "rel_pmf R q p" + and refl: "reflp R" and trans: "transp R" and antisym: "antisymP R" + shows "p = q" +proof - + from 1 2 refl trans have "rel_pmf (inf R R\\) p q" by(rule rel_pmf_inf) + also have "inf R R\\ = op =" + using refl antisym by(auto intro!: ext simp add: reflpD dest: antisymD) + finally show ?thesis unfolding pmf.rel_eq . +qed + +lemma reflp_rel_pmf: "reflp R \ reflp (rel_pmf R)" +by(blast intro: reflpI rel_pmf_reflI reflpD) + +lemma antisymP_rel_pmf: + "\ reflp R; transp R; antisymP R \ + \ antisymP (rel_pmf R)" +by(rule antisymI)(blast intro: rel_pmf_antisym) + +lemma transp_rel_pmf: + assumes "transp R" + shows "transp (rel_pmf R)" +proof (rule transpI) + fix x y z + assume "rel_pmf R x y" and "rel_pmf R y z" + hence "rel_pmf (R OO R) x z" by (simp add: pmf.rel_compp relcompp.relcompI) + thus "rel_pmf R x z" + using assms by (metis (no_types) pmf.rel_mono rev_predicate2D transp_relcompp_less_eq) +qed + +subsection \ Distributions \ + context begin @@ -639,755 +1361,4 @@ lemma set_pmf_binomial[simp]: "0 < p \ p < 1 \ set_pmf (binomial_pmf n p) = {..n}" by (simp add: set_pmf_binomial_eq) -subsection \ Monad Interpretation \ - -lemma measurable_measure_pmf[measurable]: - "(\x. measure_pmf (M x)) \ measurable (count_space UNIV) (subprob_algebra (count_space UNIV))" - by (auto simp: space_subprob_algebra intro!: prob_space_imp_subprob_space) unfold_locales - -lemma bind_measure_pmf_cong: - assumes "\x. A x \ space (subprob_algebra N)" "\x. B x \ space (subprob_algebra N)" - assumes "\i. i \ set_pmf x \ A i = B i" - shows "bind (measure_pmf x) A = bind (measure_pmf x) B" -proof (rule measure_eqI) - show "sets (measure_pmf x \= A) = sets (measure_pmf x \= B)" - using assms by (subst (1 2) sets_bind) (auto simp: space_subprob_algebra) -next - fix X assume "X \ sets (measure_pmf x \= A)" - then have X: "X \ sets N" - using assms by (subst (asm) sets_bind) (auto simp: space_subprob_algebra) - show "emeasure (measure_pmf x \= A) X = emeasure (measure_pmf x \= B) X" - using assms - by (subst (1 2) emeasure_bind[where N=N, OF _ _ X]) - (auto intro!: nn_integral_cong_AE simp: AE_measure_pmf_iff) -qed - -context -begin - -interpretation pmf_as_measure . - -lift_definition join_pmf :: "'a pmf pmf \ 'a pmf" is "\M. measure_pmf M \= measure_pmf" -proof (intro conjI) - fix M :: "'a pmf pmf" - - interpret bind: prob_space "measure_pmf M \= measure_pmf" - apply (intro measure_pmf.prob_space_bind[where S="count_space UNIV"] AE_I2) - apply (auto intro!: subprob_space_measure_pmf simp: space_subprob_algebra) - apply unfold_locales - done - show "prob_space (measure_pmf M \= measure_pmf)" - by intro_locales - show "sets (measure_pmf M \= measure_pmf) = UNIV" - by (subst sets_bind) auto - have "AE x in measure_pmf M \= measure_pmf. emeasure (measure_pmf M \= measure_pmf) {x} \ 0" - by (auto simp: AE_bind[where B="count_space UNIV"] measure_pmf_in_subprob_algebra - emeasure_bind[where N="count_space UNIV"] AE_measure_pmf_iff nn_integral_0_iff_AE - measure_pmf.emeasure_eq_measure measure_le_0_iff set_pmf_iff pmf.rep_eq) - then show "AE x in measure_pmf M \= measure_pmf. measure (measure_pmf M \= measure_pmf) {x} \ 0" - unfolding bind.emeasure_eq_measure by simp -qed - -lemma pmf_join: "pmf (join_pmf N) i = (\M. pmf M i \measure_pmf N)" -proof (transfer fixing: N i) - have N: "subprob_space (measure_pmf N)" - by (rule prob_space_imp_subprob_space) intro_locales - show "measure (measure_pmf N \= measure_pmf) {i} = integral\<^sup>L (measure_pmf N) (\M. measure M {i})" - using measurable_measure_pmf[of "\x. x"] - by (intro subprob_space.measure_bind[where N="count_space UNIV", OF N]) auto -qed (auto simp: Transfer.Rel_def rel_fun_def cr_pmf_def) - -lemma ereal_pmf_join: "ereal (pmf (join_pmf N) i) = (\\<^sup>+M. pmf M i \measure_pmf N)" - unfolding pmf_join - by (intro nn_integral_eq_integral[symmetric] measure_pmf.integrable_const_bound[where B=1]) - (auto simp: pmf_le_1 pmf_nonneg) - -lemma set_pmf_join_pmf: "set_pmf (join_pmf f) = (\p\set_pmf f. set_pmf p)" -apply(simp add: set_eq_iff set_pmf_iff pmf_join) -apply(subst integral_nonneg_eq_0_iff_AE) -apply(auto simp add: pmf_le_1 pmf_nonneg AE_measure_pmf_iff intro!: measure_pmf.integrable_const_bound[where B=1]) -done - -lift_definition return_pmf :: "'a \ 'a pmf" is "return (count_space UNIV)" - by (auto intro!: prob_space_return simp: AE_return measure_return) - -lemma join_return_pmf: "join_pmf (return_pmf M) = M" - by (simp add: integral_return pmf_eq_iff pmf_join return_pmf.rep_eq) - -lemma map_return_pmf: "map_pmf f (return_pmf x) = return_pmf (f x)" - by transfer (simp add: distr_return) - -lemma map_pmf_const[simp]: "map_pmf (\_. c) M = return_pmf c" - by transfer (auto simp: prob_space.distr_const) - -lemma set_return_pmf: "set_pmf (return_pmf x) = {x}" - by transfer (auto simp add: measure_return split: split_indicator) - -lemma pmf_return: "pmf (return_pmf x) y = indicator {y} x" - by transfer (simp add: measure_return) - -lemma nn_integral_return_pmf[simp]: "0 \ f x \ (\\<^sup>+x. f x \return_pmf x) = f x" - unfolding return_pmf.rep_eq by (intro nn_integral_return) auto - -lemma emeasure_return_pmf[simp]: "emeasure (return_pmf x) X = indicator X x" - unfolding return_pmf.rep_eq by (intro emeasure_return) auto - end - -lemma return_pmf_inj[simp]: "return_pmf x = return_pmf y \ x = y" - by (metis insertI1 set_return_pmf singletonD) - -definition "bind_pmf M f = join_pmf (map_pmf f M)" - -lemma (in pmf_as_measure) bind_transfer[transfer_rule]: - "rel_fun pmf_as_measure.cr_pmf (rel_fun (rel_fun op = pmf_as_measure.cr_pmf) pmf_as_measure.cr_pmf) op \= bind_pmf" -proof (auto simp: pmf_as_measure.cr_pmf_def rel_fun_def bind_pmf_def join_pmf.rep_eq map_pmf.rep_eq) - fix M f and g :: "'a \ 'b pmf" assume "\x. f x = measure_pmf (g x)" - then have f: "f = (\x. measure_pmf (g x))" - by auto - show "measure_pmf M \= f = distr (measure_pmf M) (count_space UNIV) g \= measure_pmf" - unfolding f by (subst bind_distr[OF _ measurable_measure_pmf]) auto -qed - -lemma ereal_pmf_bind: "pmf (bind_pmf N f) i = (\\<^sup>+x. pmf (f x) i \measure_pmf N)" - by (auto intro!: nn_integral_distr simp: bind_pmf_def ereal_pmf_join map_pmf.rep_eq) - -lemma pmf_bind: "pmf (bind_pmf N f) i = (\x. pmf (f x) i \measure_pmf N)" - by (auto intro!: integral_distr simp: bind_pmf_def pmf_join map_pmf.rep_eq) - -lemma bind_return_pmf: "bind_pmf (return_pmf x) f = f x" - unfolding bind_pmf_def map_return_pmf join_return_pmf .. - -lemma join_eq_bind_pmf: "join_pmf M = bind_pmf M id" - by (simp add: bind_pmf_def) - -lemma bind_pmf_const[simp]: "bind_pmf M (\x. c) = c" - unfolding bind_pmf_def map_pmf_const join_return_pmf .. - -lemma set_bind_pmf: "set_pmf (bind_pmf M N) = (\M\set_pmf M. set_pmf (N M))" - apply (simp add: set_eq_iff set_pmf_iff pmf_bind) - apply (subst integral_nonneg_eq_0_iff_AE) - apply (auto simp: pmf_nonneg pmf_le_1 AE_measure_pmf_iff - intro!: measure_pmf.integrable_const_bound[where B=1]) - done - - -lemma measurable_pair_restrict_pmf2: - assumes "countable A" - assumes [measurable]: "\y. y \ A \ (\x. f (x, y)) \ measurable M L" - shows "f \ measurable (M \\<^sub>M restrict_space (measure_pmf N) A) L" (is "f \ measurable ?M _") -proof - - have [measurable_cong]: "sets (restrict_space (count_space UNIV) A) = sets (count_space A)" - by (simp add: restrict_count_space) - - show ?thesis - by (intro measurable_compose_countable'[where f="\a b. f (fst b, a)" and g=snd and I=A, - unfolded pair_collapse] assms) - measurable -qed - -lemma measurable_pair_restrict_pmf1: - assumes "countable A" - assumes [measurable]: "\x. x \ A \ (\y. f (x, y)) \ measurable N L" - shows "f \ measurable (restrict_space (measure_pmf M) A \\<^sub>M N) L" -proof - - have [measurable_cong]: "sets (restrict_space (count_space UNIV) A) = sets (count_space A)" - by (simp add: restrict_count_space) - - show ?thesis - by (intro measurable_compose_countable'[where f="\a b. f (a, snd b)" and g=fst and I=A, - unfolded pair_collapse] assms) - measurable -qed - -lemma bind_commute_pmf: "bind_pmf A (\x. bind_pmf B (C x)) = bind_pmf B (\y. bind_pmf A (\x. C x y))" - unfolding pmf_eq_iff pmf_bind -proof - fix i - interpret B: prob_space "restrict_space B B" - by (intro prob_space_restrict_space measure_pmf.emeasure_eq_1_AE) - (auto simp: AE_measure_pmf_iff) - interpret A: prob_space "restrict_space A A" - by (intro prob_space_restrict_space measure_pmf.emeasure_eq_1_AE) - (auto simp: AE_measure_pmf_iff) - - interpret AB: pair_prob_space "restrict_space A A" "restrict_space B B" - by unfold_locales - - have "(\ x. \ y. pmf (C x y) i \B \A) = (\ x. (\ y. pmf (C x y) i \restrict_space B B) \A)" - by (rule integral_cong) (auto intro!: integral_pmf_restrict) - also have "\ = (\ x. (\ y. pmf (C x y) i \restrict_space B B) \restrict_space A A)" - by (intro integral_pmf_restrict B.borel_measurable_lebesgue_integral measurable_pair_restrict_pmf2 - countable_set_pmf borel_measurable_count_space) - also have "\ = (\ y. \ x. pmf (C x y) i \restrict_space A A \restrict_space B B)" - by (rule AB.Fubini_integral[symmetric]) - (auto intro!: AB.integrable_const_bound[where B=1] measurable_pair_restrict_pmf2 - simp: pmf_nonneg pmf_le_1 measurable_restrict_space1) - also have "\ = (\ y. \ x. pmf (C x y) i \restrict_space A A \B)" - by (intro integral_pmf_restrict[symmetric] A.borel_measurable_lebesgue_integral measurable_pair_restrict_pmf2 - countable_set_pmf borel_measurable_count_space) - also have "\ = (\ y. \ x. pmf (C x y) i \A \B)" - by (rule integral_cong) (auto intro!: integral_pmf_restrict[symmetric]) - finally show "(\ x. \ y. pmf (C x y) i \B \A) = (\ y. \ x. pmf (C x y) i \A \B)" . -qed - - -context -begin - -interpretation pmf_as_measure . - -lemma measure_pmf_bind: "measure_pmf (bind_pmf M f) = (measure_pmf M \= (\x. measure_pmf (f x)))" - by transfer simp - -lemma nn_integral_bind_pmf[simp]: "(\\<^sup>+x. f x \bind_pmf M N) = (\\<^sup>+x. \\<^sup>+y. f y \N x \M)" - using measurable_measure_pmf[of N] - unfolding measure_pmf_bind - apply (subst (1 3) nn_integral_max_0[symmetric]) - apply (intro nn_integral_bind[where B="count_space UNIV"]) - apply auto - done - -lemma emeasure_bind_pmf[simp]: "emeasure (bind_pmf M N) X = (\\<^sup>+x. emeasure (N x) X \M)" - using measurable_measure_pmf[of N] - unfolding measure_pmf_bind - by (subst emeasure_bind[where N="count_space UNIV"]) auto - -lemma bind_return_pmf': "bind_pmf N return_pmf = N" -proof (transfer, clarify) - fix N :: "'a measure" assume "sets N = UNIV" then show "N \= return (count_space UNIV) = N" - by (subst return_sets_cong[where N=N]) (simp_all add: bind_return') -qed - -lemma bind_return_pmf'': "bind_pmf N (\x. return_pmf (f x)) = map_pmf f N" -proof (transfer, clarify) - fix N :: "'b measure" and f :: "'b \ 'a" assume "prob_space N" "sets N = UNIV" - then show "N \= (\x. return (count_space UNIV) (f x)) = distr N (count_space UNIV) f" - by (subst bind_return_distr[symmetric]) - (auto simp: prob_space.not_empty measurable_def comp_def) -qed - -lemma bind_assoc_pmf: "bind_pmf (bind_pmf A B) C = bind_pmf A (\x. bind_pmf (B x) C)" - by transfer - (auto intro!: bind_assoc[where N="count_space UNIV" and R="count_space UNIV"] - simp: measurable_def space_subprob_algebra prob_space_imp_subprob_space) - -end - -lemma map_bind_pmf: "map_pmf f (bind_pmf M g) = bind_pmf M (\x. map_pmf f (g x))" - unfolding bind_return_pmf''[symmetric] bind_assoc_pmf[of M] .. - -lemma bind_map_pmf: "bind_pmf (map_pmf f M) g = bind_pmf M (\x. g (f x))" - unfolding bind_return_pmf''[symmetric] bind_assoc_pmf bind_return_pmf .. - -lemma map_join_pmf: "map_pmf f (join_pmf AA) = join_pmf (map_pmf (map_pmf f) AA)" - unfolding bind_pmf_def[symmetric] - unfolding bind_return_pmf''[symmetric] join_eq_bind_pmf bind_assoc_pmf - by (simp add: bind_return_pmf'') - -lemma bind_pmf_cong: - "\ p = q; \x. x \ set_pmf q \ f x = g x \ - \ bind_pmf p f = bind_pmf q g" -by(simp add: bind_pmf_def cong: map_pmf_cong) - -lemma bind_pmf_cong_simp: - "\ p = q; \x. x \ set_pmf q =simp=> f x = g x \ - \ bind_pmf p f = bind_pmf q g" -by(simp add: simp_implies_def cong: bind_pmf_cong) - -definition "pair_pmf A B = bind_pmf A (\x. bind_pmf B (\y. return_pmf (x, y)))" - -lemma pmf_pair: "pmf (pair_pmf M N) (a, b) = pmf M a * pmf N b" - unfolding pair_pmf_def pmf_bind pmf_return - apply (subst integral_measure_pmf[where A="{b}"]) - apply (auto simp: indicator_eq_0_iff) - apply (subst integral_measure_pmf[where A="{a}"]) - apply (auto simp: indicator_eq_0_iff setsum_nonneg_eq_0_iff pmf_nonneg) - done - -lemma set_pair_pmf: "set_pmf (pair_pmf A B) = set_pmf A \ set_pmf B" - unfolding pair_pmf_def set_bind_pmf set_return_pmf by auto - -lemma measure_pmf_in_subprob_space[measurable (raw)]: - "measure_pmf M \ space (subprob_algebra (count_space UNIV))" - by (simp add: space_subprob_algebra) intro_locales - -lemma nn_integral_pair_pmf': "(\\<^sup>+x. f x \pair_pmf A B) = (\\<^sup>+a. \\<^sup>+b. f (a, b) \B \A)" -proof - - have "(\\<^sup>+x. f x \pair_pmf A B) = (\\<^sup>+x. max 0 (f x) * indicator (A \ B) x \pair_pmf A B)" - by (subst nn_integral_max_0[symmetric]) - (auto simp: AE_measure_pmf_iff set_pair_pmf intro!: nn_integral_cong_AE) - also have "\ = (\\<^sup>+a. \\<^sup>+b. max 0 (f (a, b)) * indicator (A \ B) (a, b) \B \A)" - by (simp add: pair_pmf_def) - also have "\ = (\\<^sup>+a. \\<^sup>+b. max 0 (f (a, b)) \B \A)" - by (auto intro!: nn_integral_cong_AE simp: AE_measure_pmf_iff) - finally show ?thesis - unfolding nn_integral_max_0 . -qed - -lemma pair_map_pmf1: "pair_pmf (map_pmf f A) B = map_pmf (apfst f) (pair_pmf A B)" -proof (safe intro!: pmf_eqI) - fix a :: "'a" and b :: "'b" - have [simp]: "\c d. indicator (apfst f -` {(a, b)}) (c, d) = indicator (f -` {a}) c * (indicator {b} d::ereal)" - by (auto split: split_indicator) - - have "ereal (pmf (pair_pmf (map_pmf f A) B) (a, b)) = - ereal (pmf (map_pmf (apfst f) (pair_pmf A B)) (a, b))" - unfolding pmf_pair ereal_pmf_map - by (simp add: nn_integral_pair_pmf' max_def emeasure_pmf_single nn_integral_multc pmf_nonneg - emeasure_map_pmf[symmetric] del: emeasure_map_pmf) - then show "pmf (pair_pmf (map_pmf f A) B) (a, b) = pmf (map_pmf (apfst f) (pair_pmf A B)) (a, b)" - by simp -qed - -lemma pair_map_pmf2: "pair_pmf A (map_pmf f B) = map_pmf (apsnd f) (pair_pmf A B)" -proof (safe intro!: pmf_eqI) - fix a :: "'a" and b :: "'b" - have [simp]: "\c d. indicator (apsnd f -` {(a, b)}) (c, d) = indicator {a} c * (indicator (f -` {b}) d::ereal)" - by (auto split: split_indicator) - - have "ereal (pmf (pair_pmf A (map_pmf f B)) (a, b)) = - ereal (pmf (map_pmf (apsnd f) (pair_pmf A B)) (a, b))" - unfolding pmf_pair ereal_pmf_map - by (simp add: nn_integral_pair_pmf' max_def emeasure_pmf_single nn_integral_cmult nn_integral_multc pmf_nonneg - emeasure_map_pmf[symmetric] del: emeasure_map_pmf) - then show "pmf (pair_pmf A (map_pmf f B)) (a, b) = pmf (map_pmf (apsnd f) (pair_pmf A B)) (a, b)" - by simp -qed - -lemma map_pair: "map_pmf (\(a, b). (f a, g b)) (pair_pmf A B) = pair_pmf (map_pmf f A) (map_pmf g B)" - by (simp add: pair_map_pmf2 pair_map_pmf1 map_pmf_comp split_beta') - -lemma bind_pair_pmf: - assumes M[measurable]: "M \ measurable (count_space UNIV \\<^sub>M count_space UNIV) (subprob_algebra N)" - shows "measure_pmf (pair_pmf A B) \= M = (measure_pmf A \= (\x. measure_pmf B \= (\y. M (x, y))))" - (is "?L = ?R") -proof (rule measure_eqI) - have M'[measurable]: "M \ measurable (pair_pmf A B) (subprob_algebra N)" - using M[THEN measurable_space] by (simp_all add: space_pair_measure) - - note measurable_bind[where N="count_space UNIV", measurable] - note measure_pmf_in_subprob_space[simp] - - have sets_eq_N: "sets ?L = N" - by (subst sets_bind[OF sets_kernel[OF M']]) auto - show "sets ?L = sets ?R" - using measurable_space[OF M] - by (simp add: sets_eq_N space_pair_measure space_subprob_algebra) - fix X assume "X \ sets ?L" - then have X[measurable]: "X \ sets N" - unfolding sets_eq_N . - then show "emeasure ?L X = emeasure ?R X" - apply (simp add: emeasure_bind[OF _ M' X]) - apply (simp add: nn_integral_bind[where B="count_space UNIV"] pair_pmf_def measure_pmf_bind[of A] - nn_integral_measure_pmf_finite set_return_pmf emeasure_nonneg pmf_return one_ereal_def[symmetric]) - apply (subst emeasure_bind[OF _ _ X]) - apply measurable - apply (subst emeasure_bind[OF _ _ X]) - apply measurable - done -qed - -lemma join_map_return_pmf: "join_pmf (map_pmf return_pmf A) = A" - unfolding bind_pmf_def[symmetric] bind_return_pmf' .. - -lemma map_fst_pair_pmf: "map_pmf fst (pair_pmf A B) = A" - by (simp add: pair_pmf_def bind_return_pmf''[symmetric] bind_assoc_pmf bind_return_pmf bind_return_pmf') - -lemma map_snd_pair_pmf: "map_pmf snd (pair_pmf A B) = B" - by (simp add: pair_pmf_def bind_return_pmf''[symmetric] bind_assoc_pmf bind_return_pmf bind_return_pmf') - -lemma nn_integral_pmf': - "inj_on f A \ (\\<^sup>+x. pmf p (f x) \count_space A) = emeasure p (f ` A)" - by (subst nn_integral_bij_count_space[where g=f and B="f`A"]) - (auto simp: bij_betw_def nn_integral_pmf) - -lemma pmf_le_0_iff[simp]: "pmf M p \ 0 \ pmf M p = 0" - using pmf_nonneg[of M p] by simp - -lemma min_pmf_0[simp]: "min (pmf M p) 0 = 0" "min 0 (pmf M p) = 0" - using pmf_nonneg[of M p] by simp_all - -lemma pmf_eq_0_set_pmf: "pmf M p = 0 \ p \ set_pmf M" - unfolding set_pmf_iff by simp - -lemma pmf_map_inj: "inj_on f (set_pmf M) \ x \ set_pmf M \ pmf (map_pmf f M) (f x) = pmf M x" - by (auto simp: pmf.rep_eq map_pmf.rep_eq measure_distr AE_measure_pmf_iff inj_onD - intro!: measure_pmf.finite_measure_eq_AE) - -subsection \ Conditional Probabilities \ - -context - fixes p :: "'a pmf" and s :: "'a set" - assumes not_empty: "set_pmf p \ s \ {}" -begin - -interpretation pmf_as_measure . - -lemma emeasure_measure_pmf_not_zero: "emeasure (measure_pmf p) s \ 0" -proof - assume "emeasure (measure_pmf p) s = 0" - then have "AE x in measure_pmf p. x \ s" - by (rule AE_I[rotated]) auto - with not_empty show False - by (auto simp: AE_measure_pmf_iff) -qed - -lemma measure_measure_pmf_not_zero: "measure (measure_pmf p) s \ 0" - using emeasure_measure_pmf_not_zero unfolding measure_pmf.emeasure_eq_measure by simp - -lift_definition cond_pmf :: "'a pmf" is - "uniform_measure (measure_pmf p) s" -proof (intro conjI) - show "prob_space (uniform_measure (measure_pmf p) s)" - by (intro prob_space_uniform_measure) (auto simp: emeasure_measure_pmf_not_zero) - show "AE x in uniform_measure (measure_pmf p) s. measure (uniform_measure (measure_pmf p) s) {x} \ 0" - by (simp add: emeasure_measure_pmf_not_zero measure_measure_pmf_not_zero AE_uniform_measure - AE_measure_pmf_iff set_pmf.rep_eq) -qed simp - -lemma pmf_cond: "pmf cond_pmf x = (if x \ s then pmf p x / measure p s else 0)" - by transfer (simp add: emeasure_measure_pmf_not_zero pmf.rep_eq) - -lemma set_cond_pmf: "set_pmf cond_pmf = set_pmf p \ s" - by (auto simp add: set_pmf_iff pmf_cond measure_measure_pmf_not_zero split: split_if_asm) - -end - -lemma cond_map_pmf: - assumes "set_pmf p \ f -` s \ {}" - shows "cond_pmf (map_pmf f p) s = map_pmf f (cond_pmf p (f -` s))" -proof - - have *: "set_pmf (map_pmf f p) \ s \ {}" - using assms by (simp add: set_map_pmf) auto - { fix x - have "ereal (pmf (map_pmf f (cond_pmf p (f -` s))) x) = - emeasure p (f -` s \ f -` {x}) / emeasure p (f -` s)" - unfolding ereal_pmf_map cond_pmf.rep_eq[OF assms] by (simp add: nn_integral_uniform_measure) - also have "f -` s \ f -` {x} = (if x \ s then f -` {x} else {})" - by auto - also have "emeasure p (if x \ s then f -` {x} else {}) / emeasure p (f -` s) = - ereal (pmf (cond_pmf (map_pmf f p) s) x)" - using measure_measure_pmf_not_zero[OF *] - by (simp add: pmf_cond[OF *] ereal_divide' ereal_pmf_map measure_pmf.emeasure_eq_measure[symmetric] - del: ereal_divide) - finally have "ereal (pmf (cond_pmf (map_pmf f p) s) x) = ereal (pmf (map_pmf f (cond_pmf p (f -` s))) x)" - by simp } - then show ?thesis - by (intro pmf_eqI) simp -qed - -lemma bind_cond_pmf_cancel: - assumes in_S: "\x. x \ set_pmf p \ x \ S x" "\x. x \ set_pmf q \ x \ S x" - assumes S_eq: "\x y. x \ S y \ S x = S y" - and same: "\x. measure (measure_pmf p) (S x) = measure (measure_pmf q) (S x)" - shows "bind_pmf p (\x. cond_pmf q (S x)) = q" (is "?lhs = _") -proof (rule pmf_eqI) - { fix x - assume "x \ set_pmf p" - hence "set_pmf p \ (S x) \ {}" using in_S by auto - hence "measure (measure_pmf p) (S x) \ 0" - by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff) - with same have "measure (measure_pmf q) (S x) \ 0" by simp - hence "set_pmf q \ S x \ {}" - by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff) } - note [simp] = this - - fix z - have pmf_q_z: "z \ S z \ pmf q z = 0" - by(erule contrapos_np)(simp add: pmf_eq_0_set_pmf in_S) - - have "ereal (pmf ?lhs z) = \\<^sup>+ x. ereal (pmf (cond_pmf q (S x)) z) \measure_pmf p" - by(simp add: ereal_pmf_bind) - also have "\ = \\<^sup>+ x. ereal (pmf q z / measure p (S z)) * indicator (S z) x \measure_pmf p" - by(rule nn_integral_cong_AE)(auto simp add: AE_measure_pmf_iff pmf_cond same pmf_q_z in_S dest!: S_eq split: split_indicator) - also have "\ = pmf q z" using pmf_nonneg[of q z] - by (subst nn_integral_cmult)(auto simp add: measure_nonneg measure_pmf.emeasure_eq_measure same measure_pmf.prob_eq_0 AE_measure_pmf_iff pmf_eq_0_set_pmf in_S) - finally show "pmf ?lhs z = pmf q z" by simp -qed - -inductive rel_pmf :: "('a \ 'b \ bool) \ 'a pmf \ 'b pmf \ bool" -for R p q -where - "\ \x y. (x, y) \ set_pmf pq \ R x y; - map_pmf fst pq = p; map_pmf snd pq = q \ - \ rel_pmf R p q" - -bnf pmf: "'a pmf" map: map_pmf sets: set_pmf bd : "natLeq" rel: rel_pmf -proof - - show "map_pmf id = id" by (rule map_pmf_id) - show "\f g. map_pmf (f \ g) = map_pmf f \ map_pmf g" by (rule map_pmf_compose) - show "\f g::'a \ 'b. \p. (\x. x \ set_pmf p \ f x = g x) \ map_pmf f p = map_pmf g p" - by (intro map_pmf_cong refl) - - show "\f::'a \ 'b. set_pmf \ map_pmf f = op ` f \ set_pmf" - by (rule pmf_set_map) - - { fix p :: "'s pmf" - have "(card_of (set_pmf p), card_of (UNIV :: nat set)) \ ordLeq" - by (rule card_of_ordLeqI[where f="to_nat_on (set_pmf p)"]) - (auto intro: countable_set_pmf) - also have "(card_of (UNIV :: nat set), natLeq) \ ordLeq" - by (metis Field_natLeq card_of_least natLeq_Well_order) - finally show "(card_of (set_pmf p), natLeq) \ ordLeq" . } - - show "\R. rel_pmf R = - (BNF_Def.Grp {x. set_pmf x \ {(x, y). R x y}} (map_pmf fst))\\ OO - BNF_Def.Grp {x. set_pmf x \ {(x, y). R x y}} (map_pmf snd)" - by (auto simp add: fun_eq_iff BNF_Def.Grp_def OO_def rel_pmf.simps) - - { fix p :: "'a pmf" and f :: "'a \ 'b" and g x - assume p: "\z. z \ set_pmf p \ f z = g z" - and x: "x \ set_pmf p" - thus "f x = g x" by simp } - - fix R :: "'a => 'b \ bool" and S :: "'b \ 'c \ bool" - { fix p q r - assume pq: "rel_pmf R p q" - and qr:"rel_pmf S q r" - from pq obtain pq where pq: "\x y. (x, y) \ set_pmf pq \ R x y" - and p: "p = map_pmf fst pq" and q: "q = map_pmf snd pq" by cases auto - from qr obtain qr where qr: "\y z. (y, z) \ set_pmf qr \ S y z" - and q': "q = map_pmf fst qr" and r: "r = map_pmf snd qr" by cases auto - - def pr \ "bind_pmf pq (\(x, y). bind_pmf (cond_pmf qr {(y', z). y' = y}) (\(y', z). return_pmf (x, z)))" - have pr_welldefined: "\y. y \ q \ qr \ {(y', z). y' = y} \ {}" - by (force simp: q' set_map_pmf) - - have "rel_pmf (R OO S) p r" - proof (rule rel_pmf.intros) - fix x z assume "(x, z) \ pr" - then have "\y. (x, y) \ pq \ (y, z) \ qr" - by (auto simp: q pr_welldefined pr_def set_bind_pmf split_beta set_return_pmf set_cond_pmf set_map_pmf) - with pq qr show "(R OO S) x z" - by blast - next - have "map_pmf snd pr = map_pmf snd (bind_pmf q (\y. cond_pmf qr {(y', z). y' = y}))" - by (simp add: pr_def q split_beta bind_map_pmf bind_return_pmf'' map_bind_pmf map_return_pmf) - then show "map_pmf snd pr = r" - unfolding r q' bind_map_pmf by (subst (asm) bind_cond_pmf_cancel) auto - qed (simp add: pr_def map_bind_pmf split_beta map_return_pmf bind_return_pmf'' p) } - then show "rel_pmf R OO rel_pmf S \ rel_pmf (R OO S)" - by(auto simp add: le_fun_def) -qed (fact natLeq_card_order natLeq_cinfinite)+ - -lemma rel_pmf_return_pmf1: "rel_pmf R (return_pmf x) M \ (\a\M. R x a)" -proof safe - fix a assume "a \ M" "rel_pmf R (return_pmf x) M" - then obtain pq where *: "\a b. (a, b) \ set_pmf pq \ R a b" - and eq: "return_pmf x = map_pmf fst pq" "M = map_pmf snd pq" - by (force elim: rel_pmf.cases) - moreover have "set_pmf (return_pmf x) = {x}" - by (simp add: set_return_pmf) - with `a \ M` have "(x, a) \ pq" - by (force simp: eq set_map_pmf) - with * show "R x a" - by auto -qed (auto intro!: rel_pmf.intros[where pq="pair_pmf (return_pmf x) M"] - simp: map_fst_pair_pmf map_snd_pair_pmf set_pair_pmf set_return_pmf) - -lemma rel_pmf_return_pmf2: "rel_pmf R M (return_pmf x) \ (\a\M. R a x)" - by (subst pmf.rel_flip[symmetric]) (simp add: rel_pmf_return_pmf1) - -lemma rel_return_pmf[simp]: "rel_pmf R (return_pmf x1) (return_pmf x2) = R x1 x2" - unfolding rel_pmf_return_pmf2 set_return_pmf by simp - -lemma rel_pmf_False[simp]: "rel_pmf (\x y. False) x y = False" - unfolding pmf.in_rel fun_eq_iff using set_pmf_not_empty by fastforce - -lemma rel_pmf_rel_prod: - "rel_pmf (rel_prod R S) (pair_pmf A A') (pair_pmf B B') \ rel_pmf R A B \ rel_pmf S A' B'" -proof safe - assume "rel_pmf (rel_prod R S) (pair_pmf A A') (pair_pmf B B')" - then obtain pq where pq: "\a b c d. ((a, c), (b, d)) \ set_pmf pq \ R a b \ S c d" - and eq: "map_pmf fst pq = pair_pmf A A'" "map_pmf snd pq = pair_pmf B B'" - by (force elim: rel_pmf.cases) - show "rel_pmf R A B" - proof (rule rel_pmf.intros) - let ?f = "\(a, b). (fst a, fst b)" - have [simp]: "(\x. fst (?f x)) = fst o fst" "(\x. snd (?f x)) = fst o snd" - by auto - - show "map_pmf fst (map_pmf ?f pq) = A" - by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_fst_pair_pmf) - show "map_pmf snd (map_pmf ?f pq) = B" - by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_fst_pair_pmf) - - fix a b assume "(a, b) \ set_pmf (map_pmf ?f pq)" - then obtain c d where "((a, c), (b, d)) \ set_pmf pq" - by (auto simp: set_map_pmf) - from pq[OF this] show "R a b" .. - qed - show "rel_pmf S A' B'" - proof (rule rel_pmf.intros) - let ?f = "\(a, b). (snd a, snd b)" - have [simp]: "(\x. fst (?f x)) = snd o fst" "(\x. snd (?f x)) = snd o snd" - by auto - - show "map_pmf fst (map_pmf ?f pq) = A'" - by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_snd_pair_pmf) - show "map_pmf snd (map_pmf ?f pq) = B'" - by (simp add: map_pmf_comp pmf.map_comp[symmetric] eq map_snd_pair_pmf) - - fix c d assume "(c, d) \ set_pmf (map_pmf ?f pq)" - then obtain a b where "((a, c), (b, d)) \ set_pmf pq" - by (auto simp: set_map_pmf) - from pq[OF this] show "S c d" .. - qed -next - assume "rel_pmf R A B" "rel_pmf S A' B'" - then obtain Rpq Spq - where Rpq: "\a b. (a, b) \ set_pmf Rpq \ R a b" - "map_pmf fst Rpq = A" "map_pmf snd Rpq = B" - and Spq: "\a b. (a, b) \ set_pmf Spq \ S a b" - "map_pmf fst Spq = A'" "map_pmf snd Spq = B'" - by (force elim: rel_pmf.cases) - - let ?f = "(\((a, c), (b, d)). ((a, b), (c, d)))" - let ?pq = "map_pmf ?f (pair_pmf Rpq Spq)" - have [simp]: "(\x. fst (?f x)) = (\(a, b). (fst a, fst b))" "(\x. snd (?f x)) = (\(a, b). (snd a, snd b))" - by auto - - show "rel_pmf (rel_prod R S) (pair_pmf A A') (pair_pmf B B')" - by (rule rel_pmf.intros[where pq="?pq"]) - (auto simp: map_snd_pair_pmf map_fst_pair_pmf set_pair_pmf set_map_pmf map_pmf_comp Rpq Spq - map_pair) -qed - -lemma rel_pmf_reflI: - assumes "\x. x \ set_pmf p \ P x x" - shows "rel_pmf P p p" -by(rule rel_pmf.intros[where pq="map_pmf (\x. (x, x)) p"])(auto simp add: pmf.map_comp o_def set_map_pmf assms) - -lemma rel_pmf_joinI: - assumes "rel_pmf (rel_pmf P) p q" - shows "rel_pmf P (join_pmf p) (join_pmf q)" -proof - - from assms obtain pq where p: "p = map_pmf fst pq" - and q: "q = map_pmf snd pq" - and P: "\x y. (x, y) \ set_pmf pq \ rel_pmf P x y" - by cases auto - from P obtain PQ - where PQ: "\x y a b. \ (x, y) \ set_pmf pq; (a, b) \ set_pmf (PQ x y) \ \ P a b" - and x: "\x y. (x, y) \ set_pmf pq \ map_pmf fst (PQ x y) = x" - and y: "\x y. (x, y) \ set_pmf pq \ map_pmf snd (PQ x y) = y" - by(metis rel_pmf.simps) - - let ?r = "bind_pmf pq (\(x, y). PQ x y)" - have "\a b. (a, b) \ set_pmf ?r \ P a b" by(auto simp add: set_bind_pmf intro: PQ) - moreover have "map_pmf fst ?r = join_pmf p" "map_pmf snd ?r = join_pmf q" - by(simp_all add: bind_pmf_def map_join_pmf pmf.map_comp o_def split_def p q x y cong: pmf.map_cong) - ultimately show ?thesis .. -qed - -lemma rel_pmf_bindI: - assumes pq: "rel_pmf R p q" - and fg: "\x y. R x y \ rel_pmf P (f x) (g y)" - shows "rel_pmf P (bind_pmf p f) (bind_pmf q g)" -unfolding bind_pmf_def -by(rule rel_pmf_joinI)(auto simp add: pmf.rel_map intro: pmf.rel_mono[THEN le_funD, THEN le_funD, THEN le_boolD, THEN mp, OF _ pq] fg) - -text {* - Proof that @{const rel_pmf} preserves orders. - Antisymmetry proof follows Thm. 1 in N. Saheb-Djahromi, Cpo's of measures for nondeterminism, - Theoretical Computer Science 12(1):19--37, 1980, - @{url "http://dx.doi.org/10.1016/0304-3975(80)90003-1"} -*} - -lemma - assumes *: "rel_pmf R p q" - and refl: "reflp R" and trans: "transp R" - shows measure_Ici: "measure p {y. R x y} \ measure q {y. R x y}" (is ?thesis1) - and measure_Ioi: "measure p {y. R x y \ \ R y x} \ measure q {y. R x y \ \ R y x}" (is ?thesis2) -proof - - from * obtain pq - where pq: "\x y. (x, y) \ set_pmf pq \ R x y" - and p: "p = map_pmf fst pq" - and q: "q = map_pmf snd pq" - by cases auto - show ?thesis1 ?thesis2 unfolding p q map_pmf.rep_eq using refl trans - by(auto 4 3 simp add: measure_distr reflpD AE_measure_pmf_iff intro!: measure_pmf.finite_measure_mono_AE dest!: pq elim: transpE) -qed - -lemma rel_pmf_inf: - fixes p q :: "'a pmf" - assumes 1: "rel_pmf R p q" - assumes 2: "rel_pmf R q p" - and refl: "reflp R" and trans: "transp R" - shows "rel_pmf (inf R R\\) p q" -proof - let ?E = "\x. {y. R x y \ R y x}" - let ?\E = "\x. measure q (?E x)" - { fix x - have "measure p (?E x) = measure p ({y. R x y} - {y. R x y \ \ R y x})" - by(auto intro!: arg_cong[where f="measure p"]) - also have "\ = measure p {y. R x y} - measure p {y. R x y \ \ R y x}" - by (rule measure_pmf.finite_measure_Diff) auto - also have "measure p {y. R x y \ \ R y x} = measure q {y. R x y \ \ R y x}" - using 1 2 refl trans by(auto intro!: Orderings.antisym measure_Ioi) - also have "measure p {y. R x y} = measure q {y. R x y}" - using 1 2 refl trans by(auto intro!: Orderings.antisym measure_Ici) - also have "measure q {y. R x y} - measure q {y. R x y \ ~ R y x} = - measure q ({y. R x y} - {y. R x y \ \ R y x})" - by(rule measure_pmf.finite_measure_Diff[symmetric]) auto - also have "\ = ?\E x" - by(auto intro!: arg_cong[where f="measure q"]) - also note calculation } - note eq = this - - def pq \ "bind_pmf p (\x. bind_pmf (cond_pmf q (?E x)) (\y. return_pmf (x, y)))" - - show "map_pmf fst pq = p" - by(simp add: pq_def map_bind_pmf map_return_pmf bind_return_pmf') - - show "map_pmf snd pq = q" - unfolding pq_def map_bind_pmf map_return_pmf bind_return_pmf' snd_conv - by(subst bind_cond_pmf_cancel)(auto simp add: reflpD[OF \reflp R\] eq intro: transpD[OF \transp R\]) - - fix x y - assume "(x, y) \ set_pmf pq" - moreover - { assume "x \ set_pmf p" - hence "measure (measure_pmf p) (?E x) \ 0" - by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff intro: reflpD[OF \reflp R\]) - hence "measure (measure_pmf q) (?E x) \ 0" using eq by simp - hence "set_pmf q \ {y. R x y \ R y x} \ {}" - by(auto simp add: measure_pmf.prob_eq_0 AE_measure_pmf_iff) } - ultimately show "inf R R\\ x y" - by(auto simp add: pq_def set_bind_pmf set_return_pmf set_cond_pmf) -qed - -lemma rel_pmf_antisym: - fixes p q :: "'a pmf" - assumes 1: "rel_pmf R p q" - assumes 2: "rel_pmf R q p" - and refl: "reflp R" and trans: "transp R" and antisym: "antisymP R" - shows "p = q" -proof - - from 1 2 refl trans have "rel_pmf (inf R R\\) p q" by(rule rel_pmf_inf) - also have "inf R R\\ = op =" - using refl antisym by(auto intro!: ext simp add: reflpD dest: antisymD) - finally show ?thesis unfolding pmf.rel_eq . -qed - -lemma reflp_rel_pmf: "reflp R \ reflp (rel_pmf R)" -by(blast intro: reflpI rel_pmf_reflI reflpD) - -lemma antisymP_rel_pmf: - "\ reflp R; transp R; antisymP R \ - \ antisymP (rel_pmf R)" -by(rule antisymI)(blast intro: rel_pmf_antisym) - -lemma transp_rel_pmf: - assumes "transp R" - shows "transp (rel_pmf R)" -proof (rule transpI) - fix x y z - assume "rel_pmf R x y" and "rel_pmf R y z" - hence "rel_pmf (R OO R) x z" by (simp add: pmf.rel_compp relcompp.relcompI) - thus "rel_pmf R x z" - using assms by (metis (no_types) pmf.rel_mono rev_predicate2D transp_relcompp_less_eq) -qed - -end -