Skip to content

Commit 8f71d81

Browse files
[theories/modules] law of total probability
Add module-based law of total probability for distributions with finite support.
1 parent 042456e commit 8f71d81

1 file changed

Lines changed: 281 additions & 0 deletions

File tree

theories/modules/TotalProb.ec

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
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

Comments
 (0)