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