Skip to content

Commit 978a344

Browse files
namasikanamstrub
authored andcommitted
Add another example for eHoare
1 parent 51d01ff commit 978a344

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

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

0 commit comments

Comments
 (0)