|
| 1 | +(*^ This theory proves a module-based law of total probability for |
| 2 | + distributions with finite support, and then specializes it to |
| 3 | + `DBool.dbool`, `drange` and `duniform`. ^*) |
| 4 | + |
| 5 | +require import AllCore List StdOrder StdBigop Distr DBool Finite. |
| 6 | +require EventPartitioning. |
| 7 | +import RealOrder Bigreal BRA. |
| 8 | + |
| 9 | +(*& General abstract theory &*) |
| 10 | + |
| 11 | +abstract theory TotalGeneral. |
| 12 | + |
| 13 | +(*& theory parameter: additional input &*) |
| 14 | + |
| 15 | +type input. |
| 16 | + |
| 17 | +(*& theory parameter: type of distribution &*) |
| 18 | + |
| 19 | +type t. |
| 20 | + |
| 21 | +(*& A module with a `main` procedure taking in an input plus |
| 22 | + a value of type `t`, and returning a boolean result. &*) |
| 23 | + |
| 24 | +module type T = { |
| 25 | + proc main(i : input, x : t) : bool |
| 26 | +}. |
| 27 | + |
| 28 | +(*& For a module `M` with module type `T` and a distribution `dt` for |
| 29 | + `t` plus an input `i`, `Rand(M).f(dt, i)` samples a value `x` from |
| 30 | + `dt`, passes it to `M.main` along with `i`, and returns the |
| 31 | + boolean `M.main` returns. &*) |
| 32 | + |
| 33 | +module Rand(M : T) = { |
| 34 | + proc f(dt : t distr, i : input) : bool = { |
| 35 | + var b : bool; var x : t; |
| 36 | + x <$ dt; |
| 37 | + b <@ M.main(i, x); |
| 38 | + return b; |
| 39 | + } |
| 40 | +}. |
| 41 | + |
| 42 | +(* skip to end of section for main lemma *) |
| 43 | + |
| 44 | +section. |
| 45 | + |
| 46 | +declare module M <: T. |
| 47 | + |
| 48 | +local module RandAux = { |
| 49 | + var x : t (* a global variable *) |
| 50 | + |
| 51 | + proc f(dt : t distr, i : input) : bool = { |
| 52 | + var b : bool; |
| 53 | + x <$ dt; |
| 54 | + b <@ M.main(i, x); |
| 55 | + return b; |
| 56 | + } |
| 57 | +}. |
| 58 | + |
| 59 | +local clone EventPartitioning as EP with |
| 60 | + type input <- t distr * input, |
| 61 | + type output <- bool |
| 62 | +proof *. |
| 63 | + |
| 64 | +local clone EP.ListPartitioning as EPL with |
| 65 | + type partition <- t |
| 66 | +proof *. |
| 67 | + |
| 68 | +local op x_of_glob_RA (g : (glob RandAux)) : t = g.`2. |
| 69 | +local op phi (_ : t distr * input) (g : glob RandAux) (_ : bool) : t = |
| 70 | + x_of_glob_RA g. |
| 71 | +local op E (_ : t distr * input) (_ : glob RandAux) (o : bool) : bool = o. |
| 72 | + |
| 73 | +local lemma RandAux_partition_eq (dt' : t distr) (i' : input) (x' : t) &m : |
| 74 | + Pr[RandAux.f(dt', i') @ &m : res /\ x_of_glob_RA (glob RandAux) = x'] = |
| 75 | + mu1 dt' x' * Pr[M.main(i', x') @ &m : res]. |
| 76 | +proof. |
| 77 | +byphoare |
| 78 | + (: |
| 79 | + dt = dt' /\ i = i' /\ (glob M) = (glob M){m} ==> |
| 80 | + res /\ x_of_glob_RA (glob RandAux) = x') => //. |
| 81 | +proc; rewrite /x_of_glob_RA /=. |
| 82 | +seq 1 : |
| 83 | + (RandAux.x = x') |
| 84 | + (mu1 dt' x') |
| 85 | + Pr[M.main(i', x') @ &m : res] |
| 86 | + (1%r - mu1 dt x') |
| 87 | + 0%r |
| 88 | + (i = i' /\ (glob M) = (glob M){m}) => //. |
| 89 | ++ by auto. |
| 90 | ++ by rnd (pred1 x'); auto. |
| 91 | ++ call (: i = i' /\ x = x' /\ glob M = (glob M){m} ==> res). |
| 92 | + + bypr => &hr [#] -> -> glob_eq. |
| 93 | + by byequiv (: ={i, x, glob M} ==> ={res}) => //; sim. |
| 94 | ++ by auto. |
| 95 | +by hoare; call (: true); auto; smt(). |
| 96 | +qed. |
| 97 | +
|
| 98 | +lemma total_prob' (supp : t list) (dt' : t distr) (i' : input) &m : |
| 99 | + is_finite_for (support dt') supp => |
| 100 | + Pr[Rand(M).f(dt', i') @ &m : res] = |
| 101 | + big predT |
| 102 | + (fun x' => mu1 dt' x' * Pr[M.main(i', x') @ &m : res]) |
| 103 | + supp. |
| 104 | +proof. |
| 105 | +move => [uniq_supp supp_iff]. |
| 106 | +have ->: |
| 107 | + Pr[Rand(M).f(dt', i') @ &m : res] = Pr[RandAux.f(dt', i') @ &m : res]. |
| 108 | + + by byequiv (_ : ={dt, i, glob M} ==> ={res}) => //; proc; sim. |
| 109 | +rewrite (EPL.list_partitioning RandAux (dt', i') E phi supp &m) //. |
| 110 | +have -> /= : |
| 111 | + Pr[RandAux.f(dt', i') @ &m: res /\ ! (x_of_glob_RA (glob RandAux) \in supp)] = |
| 112 | + 0%r. |
| 113 | ++ byphoare (: dt = dt' /\ i = i' ==> _) => //; proc. |
| 114 | + seq 1 : |
| 115 | + (RandAux.x \in supp) |
| 116 | + 1%r |
| 117 | + 0%r |
| 118 | + 0%r |
| 119 | + 1%r => //. |
| 120 | + + by hoare; call (: true); auto; smt(). |
| 121 | + by rnd pred0; auto; smt(mu0). |
| 122 | +by congr; apply fun_ext => x'; rewrite RandAux_partition_eq. |
| 123 | +qed. |
| 124 | +
|
| 125 | +end section. |
| 126 | +
|
| 127 | +(*& total probability lemma for distributions with finite support &*) |
| 128 | +
|
| 129 | +lemma total_prob (M <: T) (supp : t list) (dt : t distr) (i : input) &m : |
| 130 | + is_finite_for (support dt) supp => |
| 131 | + Pr[Rand(M).f(dt, i) @ &m : res] = |
| 132 | + big predT |
| 133 | + (fun (x : t) => mu1 dt x * Pr[M.main(i, x) @ &m : res]) |
| 134 | + supp. |
| 135 | +proof. exact: (total_prob' M). qed. |
| 136 | + |
| 137 | +end TotalGeneral. |
| 138 | + |
| 139 | +(*& Specialization to `DBool.dbool` &*) |
| 140 | + |
| 141 | +abstract theory TotalBool. |
| 142 | + |
| 143 | +clone include TotalGeneral with |
| 144 | + type t <- bool |
| 145 | +proof *. |
| 146 | + |
| 147 | +(*& total probability lemma for `DBool.dbool` &*) |
| 148 | + |
| 149 | +lemma total_prob_bool (M <: T) (i : input) &m : |
| 150 | + Pr[Rand(M).f(DBool.dbool, i) @ &m : res] = |
| 151 | + Pr[M.main(i, true) @ &m : res] / 2%r + |
| 152 | + Pr[M.main(i, false) @ &m : res] / 2%r. |
| 153 | +proof. |
| 154 | +rewrite (total_prob M [true; false]) //. |
| 155 | ++ smt(supp_dbool). |
| 156 | +by rewrite 2!big_cons big_nil /= 2!dbool1E. |
| 157 | +qed. |
| 158 | + |
| 159 | +end TotalBool. |
| 160 | + |
| 161 | +(*& Specialization to `drange` &*) |
| 162 | + |
| 163 | +abstract theory TotalRange. |
| 164 | + |
| 165 | +clone include TotalGeneral with |
| 166 | + type t <- int |
| 167 | +proof *. |
| 168 | + |
| 169 | +(*& total probability lemma for `drange` &*) |
| 170 | + |
| 171 | +lemma total_prob_drange (M <: T) (m n : int) (i : input) &m : |
| 172 | + m < n => |
| 173 | + Pr[Rand(M).f(drange m n, i) @ &m : res] = |
| 174 | + bigi predT |
| 175 | + (fun (j : int) => Pr[M.main(i, j) @ &m : res] / (n - m)%r) |
| 176 | + m n. |
| 177 | +proof. |
| 178 | +move => lt_m_n; rewrite (total_prob M (range m n)). |
| 179 | ++ by rewrite /is_finite_for; smt(range_uniq mem_range supp_drange). |
| 180 | +by apply: eq_big_seq=> |> y; rewrite drange1E mem_range=> ->. |
| 181 | +qed. |
| 182 | + |
| 183 | +end TotalRange. |
| 184 | + |
| 185 | +(*& Specialization to `duniform` &*) |
| 186 | + |
| 187 | +abstract theory TotalUniform. |
| 188 | + |
| 189 | +(*& theory parameter: type &*) |
| 190 | + |
| 191 | +type t. |
| 192 | + |
| 193 | +clone include TotalGeneral with |
| 194 | + type t <- t |
| 195 | +proof *. |
| 196 | + |
| 197 | +(*& total probability lemma for `duniform` &*) |
| 198 | + |
| 199 | +lemma total_prob_uniform (M <: T) (xs : t list) (i : input) &m : |
| 200 | + uniq xs => xs <> [] => |
| 201 | + Pr[Rand(M).f(duniform xs, i) @ &m : res] = |
| 202 | + big predT |
| 203 | + (fun (x : t) => Pr[M.main(i, x) @ &m : res] / (size xs)%r) |
| 204 | + xs. |
| 205 | +proof. |
| 206 | +move => uniq_xs xs_ne_nil; rewrite (total_prob M xs). |
| 207 | ++ smt(supp_duniform). |
| 208 | +by apply: eq_big_seq=> |> x; rewrite duniform1E_uniq=> // ->. |
| 209 | +qed. |
| 210 | + |
| 211 | +end TotalUniform. |
0 commit comments