Skip to content

Commit f7fcac0

Browse files
committed
another example for eHoare
1 parent a78d1cf commit f7fcac0

File tree

1 file changed

+235
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)