Skip to content

Commit 587d28f

Browse files
alleystoughtonfdupressstrub
committed
[theories/modules] add law of total probability for lossless
distributions with finite support Co-authored-by: François Dupressoir <fdupress@gmail.com> Co-authored-by: Pierre-Yves Strub <pierre-yves.strub@pqshield.com>
1 parent 70f8dfc commit 587d28f

1 file changed

Lines changed: 211 additions & 0 deletions

File tree

theories/modules/TotalProb.ec

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

Comments
 (0)