Skip to content

Commit 966efa8

Browse files
committed
another example for eHoare
1 parent a78d1cf commit 966efa8

File tree

1 file changed

+232
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)