Skip to content

Commit 3161c60

Browse files
committed
another example for eHoare
1 parent a78d1cf commit 3161c60

File tree

1 file changed

+248
-0
lines changed

1 file changed

+248
-0
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
require import AllCore Array Real RealExp List.
2+
(*---*) import RField.
3+
require import Distr DBool Xreal.
4+
(*---*) import Biased.
5+
require import StdOrder.
6+
(*---*) import RealOrder.
7+
8+
lemma mul0z (x : int) : 0 * x = 0.
9+
proof. by auto. qed.
10+
11+
lemma neg0: -0 = 0.
12+
proof. by auto. qed.
13+
14+
lemma xle_rle:
15+
forall (x y : real),
16+
0%r <= x <= y => x%xr <= y%xr.
17+
proof.
18+
move => x y [??] /=.
19+
by rewrite !to_pos_pos //; exact (ler_trans x).
20+
qed.
21+
22+
lemma Ep_dbiased (p : real) (f : bool -> xreal) :
23+
0%r <= p <= 1%r => Ep (dbiased p) f = p ** f true + (1%r - p) ** f false.
24+
proof.
25+
move => ?.
26+
rewrite (Ep_fin [true; false]) //.
27+
+ by case.
28+
by rewrite /BXA.big /predT /= !dbiased1E /= !clamp_id //.
29+
qed.
30+
31+
(* uniformly sampling a 2-d boolean array of size n x m *)
32+
module M = {
33+
proc sample (n : int, m : int, a : bool array) : (bool array) = {
34+
var i, j : int;
35+
var b : bool;
36+
i <- 0;
37+
while (i < n) {
38+
j <- 0;
39+
while (j < m) {
40+
b <$ dbiased 0.5;
41+
a.[i * m + j] <- b;
42+
j <- j + 1;
43+
}
44+
i <- i + 1;
45+
}
46+
return a;
47+
}
48+
}.
49+
50+
op outer_shape_pred (i n m : int) (a a' : bool array) =
51+
0 <= i <= n
52+
/\ 0 <= m
53+
/\ size a = n * m
54+
/\ size a = size a'.
55+
56+
op shape_pred (i j n m : int) (a a' : bool array) =
57+
0 <= i < n
58+
/\ 0 <= j <= m
59+
/\ size a = n * m
60+
/\ size a = size a'.
61+
62+
op row_eq_upto (i m : int) (a1 a2 : bool array) =
63+
forall (i' j' : int),
64+
0 <= i' < i
65+
=> 0 <= j' < m
66+
=> a1.[i' * m + j'] = a2.[i' * m + j'].
67+
68+
op cell_eq_upto (i j m : int) (a1 a2 : bool array) =
69+
forall (j' : int),
70+
0 <= j' < j
71+
=> a1.[i * m + j'] = a2.[i * m + j'].
72+
73+
lemma row_eq_upto_increase (i m : int) (a1 a2 : bool array):
74+
0 <= i
75+
=> (row_eq_upto i m a1 a2 /\ cell_eq_upto i m m a1 a2
76+
<=> row_eq_upto (i + 1) m a1 a2).
77+
proof.
78+
move => ? @/row_eq_upto @/cell_eq_upto; split.
79+
- move => ? i' j' *.
80+
by case: (i' < i) => /#.
81+
- move => H; split.
82+
- move => i' j' ??.
83+
have ?: 0 <= i' < i + 1 by smt().
84+
by have := H i' j' _ _ => //.
85+
- by have := H i => /#.
86+
qed.
87+
88+
lemma cell_eq_upto_false (i j' j m : int) (a1 a2 : bool array) :
89+
0 <= j' < j
90+
=> a1.[i * m + j'] <> a2.[i * m + j']
91+
=> cell_eq_upto i j m a1 a2 = false.
92+
proof. by smt(). qed.
93+
94+
lemma cell_eq_upto_split (i j m : int) (a1 a2 : bool array) :
95+
0 <= j < m
96+
=> (cell_eq_upto i (j + 1) m a1 a2
97+
<=> (cell_eq_upto i j m a1 a2
98+
/\ a1.[i * m + j] = a2.[i * m + j])
99+
).
100+
proof.
101+
move => ? @/cell_eq_upto; split.
102+
- move => H; split.
103+
- move => j' ?.
104+
have ?: 0 <= j' < j + 1 by smt().
105+
have := H j' _ => //.
106+
- by smt().
107+
- move => ? j' ?.
108+
by case (j' < j) => /#.
109+
qed.
110+
111+
lemma row_eq_upto_unrelated_set (i m x : int) (v : bool) (a1 a2 : bool array):
112+
i * m <= x < size a1
113+
=> (row_eq_upto i m a1 a2 <=> row_eq_upto i m a1.[x <- v] a2).
114+
proof.
115+
move => ?.
116+
rewrite /row_eq_upto; split.
117+
- move => ? i' j' ??.
118+
rewrite get_set 1:/#.
119+
have -> /=: !(i' * m + j' = x) by smt().
120+
by smt().
121+
- move => ? i' j' ??.
122+
by rewrite (_: a1.[i' * m + j'] = a1.[x <- v].[i' * m + j']) 1:get_set /#.
123+
qed.
124+
125+
lemma cell_eq_upto_unrelated_set (i j m x : int) (v : bool) (a1 a2 : bool array) :
126+
0 <= i /\ 0 <= j < m /\ i * m + j <= x < size a1
127+
=> (cell_eq_upto i j m a1 a2 <=> cell_eq_upto i j m a1.[x <- v] a2).
128+
proof.
129+
move => [#] ?????.
130+
rewrite /cell_eq_upto; split.
131+
- move => ? j' ?.
132+
rewrite get_set 1:/#.
133+
have -> /=: !(i * m + j' = x) by smt().
134+
by smt().
135+
- move => ? j' ?.
136+
by rewrite (_: a1.[i * m + j'] = a1.[x <- v].[i * m + j']) 1:get_set /#.
137+
qed.
138+
139+
(* The probability of every possible boolean matrix of size n x m is no more than 2 ^ -(n * m) *)
140+
lemma L:
141+
forall (a0 : bool array),
142+
ehoare [M.sample :
143+
(0 <= arg.`1
144+
/\ 0 <= arg.`2
145+
/\ size arg.`3 = arg.`1 * arg.`2
146+
/\ size arg.`3 = size a0)
147+
`|` (1%r / (2%r ^ (n * m)))%xr ==> (res = a0)%xr].
148+
proof.
149+
move => a0.
150+
proc.
151+
while ((0 <= i <= n
152+
/\ 0 <= m
153+
/\ size a = n * m
154+
/\ size a0 = size a)
155+
`|` (2%r ^ ((-(n - i) * m)%r))%xr
156+
* (row_eq_upto i m a a0)%xr).
157+
(* !cond => inv => pos_f <= inv_f *)
158+
+ move => &hr.
159+
rewrite xle_cxr_r => *. (* Bug in EC: the precedent is lost when rewriting xle_cxr_r twice. *)
160+
rewrite xle_cxr_r => *.
161+
have ->: n{hr} - i{hr} = 0 by smt().
162+
rewrite mul0z neg0 rpow0 mul1m_simpl.
163+
apply xle_rle; split => * ;1: by smt().
164+
exact le_b2r.
165+
(* {cond /\ inv | inv_f} c {inv | inv_f} *)
166+
+ wp.
167+
while (( 0 <= i < n
168+
/\ 0 <= j <= m
169+
/\ size a = n * m
170+
/\ size a = size a0)
171+
`|` (2%r ^ ((-((n - i) * m - j))%r))%xr
172+
* (row_eq_upto i m a a0 /\ cell_eq_upto i j m a a0)%xr).
173+
(* !cond => inv => pos_f <= inv_f *)
174+
+ move => &hr />.
175+
rewrite xle_cxr_r => *.
176+
rewrite xle_cxr_l => *.
177+
+ by smt().
178+
+ rewrite (_: - (n{hr} - (i{hr} + 1)) * m{hr}
179+
= - ((n{hr} - i{hr}) * m{hr} - j{hr})) //= 1:/#.
180+
rewrite (_: j{hr} = m{hr}) 1:/#.
181+
rewrite -row_eq_upto_increase 1:/#.
182+
rewrite ler_eqVlt; left; reflexivity.
183+
(* {cond /\ inv | inv_f} c {inv | inv_f} *)
184+
+ wp; skip.
185+
move => &hr.
186+
move => />.
187+
rewrite xle_cxr_r => [#] 5? Hsize *.
188+
rewrite Ep_dbiased /= 1:/#.
189+
rewrite (_: ((0 <= i{hr} < n{hr}) <=> true)) 1:/#.
190+
rewrite (_: ((0 <= j{hr} + 1 <= m{hr}) <=> true)) 1:/#.
191+
rewrite !size_set.
192+
rewrite (_: ((size a{hr} = n{hr} * m{hr}) <=> true)) 1:/#.
193+
rewrite (_: (size a{hr} = size a0) <=> true) /= 1:/#.
194+
rewrite !to_pos_pos 1,2,3,4,5:#smt:(rpow_gt0 b2r_ge0).
195+
rewrite !cell_eq_upto_split 1,2:/#.
196+
rewrite !get_set //=.
197+
- split; 1: by smt().
198+
move => ?.
199+
by apply (IntOrder.ltr_le_trans ((n{hr} - 1) * m{hr} + m{hr})) => /#.
200+
- split; 1: by smt().
201+
move => ?.
202+
by apply (IntOrder.ltr_le_trans ((n{hr} - 1) * m{hr} + m{hr})) => /#.
203+
case (a0.[i{hr} * m{hr} + j{hr}]) => Hcase /=.
204+
+ rewrite -row_eq_upto_unrelated_set.
205+
- split; 1: by smt().
206+
move => ?.
207+
by apply (IntOrder.ltr_le_trans ((n{hr} - 1) * m{hr} + m{hr})) => /#.
208+
rewrite -cell_eq_upto_unrelated_set.
209+
- do! split; 1,2,3: by smt().
210+
move => ?.
211+
by apply (IntOrder.ltr_le_trans ((n{hr} - 1) * m{hr} + m{hr})) => /#.
212+
rewrite -{2} (rpow1 2%r) //.
213+
rewrite -rpowN // -mulrA.
214+
rewrite (mulrC
215+
(b2r
216+
(row_eq_upto i{hr} m{hr} a{hr} a0 /\
217+
cell_eq_upto i{hr} j{hr} m{hr} a{hr} a0))
218+
(2%r ^ - 1%r)).
219+
by rewrite mulrA -rpowD // /#.
220+
+ rewrite /= -row_eq_upto_unrelated_set.
221+
- split; 1: by smt().
222+
move => ?.
223+
by apply (IntOrder.ltr_le_trans ((n{hr} - 1) * m{hr} + m{hr})) => /#.
224+
rewrite -cell_eq_upto_unrelated_set.
225+
- do! split; 1,2,3: by smt().
226+
move => ?.
227+
by apply (IntOrder.ltr_le_trans ((n{hr} - 1) * m{hr} + m{hr})) => /#.
228+
rewrite -{2} (rpow1 2%r) //.
229+
rewrite -rpowN // -mulrA.
230+
rewrite (mulrC
231+
(b2r
232+
(row_eq_upto i{hr} m{hr} a{hr} a0 /\
233+
cell_eq_upto i{hr} j{hr} m{hr} a{hr} a0))
234+
(2%r ^ - 1%r)).
235+
by rewrite mulrA -rpowD // /#.
236+
(* pre => inv *)
237+
+ wp; skip.
238+
move => &hr />.
239+
rewrite xle_cxr_r => *.
240+
rewrite xle_cxr_l 1:/#.
241+
rewrite (_: cell_eq_upto i{hr} 0 m{hr} a{hr} a0 = true) //= 1:/#.
242+
wp.
243+
skip => /> &hr.
244+
rewrite xle_cxr_r => *.
245+
rewrite xle_cxr_l 1:/#.
246+
rewrite fromintN rpowN //= rpow_int //=.
247+
by rewrite (_: row_eq_upto 0 m{hr} a{hr} a0 = true) //= 1:/#.
248+
qed.

0 commit comments

Comments
 (0)