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