|
| 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. by smt(). qed. |
| 75 | + |
| 76 | +lemma cell_eq_upto_false (i j' j m : int) (a1 a2 : bool array) : |
| 77 | + 0 <= j' < j |
| 78 | + => a1.[i * m + j'] <> a2.[i * m + j'] |
| 79 | + => cell_eq_upto i j m a1 a2 = false. |
| 80 | +proof. by smt(). qed. |
| 81 | + |
| 82 | +lemma cell_eq_upto_split (i j m : int) (a1 a2 : bool array) : |
| 83 | + 0 <= j < m |
| 84 | + => (cell_eq_upto i (j + 1) m a1 a2 |
| 85 | + <=> (cell_eq_upto i j m a1 a2 |
| 86 | + /\ a1.[i * m + j] = a2.[i * m + j]) |
| 87 | + ). |
| 88 | +proof. by smt(). qed. |
| 89 | + |
| 90 | +lemma mul_add_lt (i j n m : int) : |
| 91 | + 0 <= i < n => 0 <= j < m => i * m + j < n * m. |
| 92 | +proof. |
| 93 | +by rewrite (_: n * m = (n - 1) * m + m) /#. |
| 94 | +qed. |
| 95 | + |
| 96 | +lemma row_eq_upto_unrelated_set (i m x : int) (v : bool) (a1 a2 : bool array): |
| 97 | + i * m <= x < size a1 |
| 98 | + => (row_eq_upto i m a1 a2 <=> row_eq_upto i m a1.[x <- v] a2). |
| 99 | +proof. |
| 100 | +by smt(get_set mul_add_lt). |
| 101 | +qed. |
| 102 | + |
| 103 | +lemma cell_eq_upto_unrelated_set (i j m x : int) (v : bool) (a1 a2 : bool array) : |
| 104 | + 0 <= i /\ 0 <= j < m /\ i * m + j <= x < size a1 |
| 105 | + => (cell_eq_upto i j m a1 a2 <=> cell_eq_upto i j m a1.[x <- v] a2). |
| 106 | +proof. |
| 107 | +by smt(get_set). |
| 108 | +qed. |
| 109 | + |
| 110 | +(* The probability of every possible boolean matrix of size n x m is no more than 2 ^ -(n * m) *) |
| 111 | +lemma L: |
| 112 | + forall (a0 : bool array), |
| 113 | + ehoare [M.sample : |
| 114 | + (0 <= arg.`1 |
| 115 | + /\ 0 <= arg.`2 |
| 116 | + /\ size arg.`3 = arg.`1 * arg.`2 |
| 117 | + /\ size arg.`3 = size a0) |
| 118 | + `|` (1%r / (2%r ^ (n * m)))%xr ==> (res = a0)%xr]. |
| 119 | +proof. |
| 120 | +move => a0. |
| 121 | +proc. |
| 122 | +while ((0 <= i <= n |
| 123 | + /\ 0 <= m |
| 124 | + /\ size a = n * m |
| 125 | + /\ size a0 = size a) |
| 126 | + `|` (2%r ^ ((-(n - i) * m)%r))%xr |
| 127 | + * (row_eq_upto i m a a0)%xr). |
| 128 | +(* !cond => inv => pos_f <= inv_f *) |
| 129 | ++ move => &hr. |
| 130 | + rewrite xle_cxr_r => *. (* Bug in EC: the precedent is lost when rewriting xle_cxr_r twice. *) |
| 131 | + rewrite xle_cxr_r => *. |
| 132 | + have ->: n{hr} - i{hr} = 0 by smt(). |
| 133 | + rewrite mul0z neg0 rpow0 mul1m_simpl. |
| 134 | + apply xle_rle; split => * ;1: by smt(). |
| 135 | + exact le_b2r. |
| 136 | +(* {cond /\ inv | inv_f} c {inv | inv_f} *) |
| 137 | ++ wp. |
| 138 | + while (( 0 <= i < n |
| 139 | + /\ 0 <= j <= m |
| 140 | + /\ size a = n * m |
| 141 | + /\ size a = size a0) |
| 142 | + `|` (2%r ^ ((-((n - i) * m - j))%r))%xr |
| 143 | + * (row_eq_upto i m a a0 /\ cell_eq_upto i j m a a0)%xr). |
| 144 | + (* !cond => inv => pos_f <= inv_f *) |
| 145 | + + move => &hr />. |
| 146 | + rewrite xle_cxr_r => *. |
| 147 | + rewrite xle_cxr_l => *. |
| 148 | + + by smt(). |
| 149 | + + rewrite (_: - (n{hr} - (i{hr} + 1)) * m{hr} |
| 150 | + = - ((n{hr} - i{hr}) * m{hr} - j{hr})) //= 1:/#. |
| 151 | + rewrite (_: j{hr} = m{hr}) 1:/#. |
| 152 | + rewrite -row_eq_upto_increase 1:/#. |
| 153 | + rewrite ler_eqVlt; left; reflexivity. |
| 154 | + (* {cond /\ inv | inv_f} c {inv | inv_f} *) |
| 155 | + + wp; skip. |
| 156 | + move => &hr. |
| 157 | + move => />. |
| 158 | + rewrite xle_cxr_r => [#] 5? Hsize *. |
| 159 | + rewrite Ep_dbiased /= 1:/#. |
| 160 | + rewrite (_: ((0 <= i{hr} < n{hr}) <=> true)) 1:/#. |
| 161 | + rewrite (_: ((0 <= j{hr} + 1 <= m{hr}) <=> true)) 1:/#. |
| 162 | + rewrite !size_set. |
| 163 | + rewrite (_: ((size a{hr} = n{hr} * m{hr}) <=> true)) 1:/#. |
| 164 | + rewrite (_: (size a{hr} = size a0) <=> true) /= 1:/#. |
| 165 | + rewrite !to_pos_pos 1,2,3,4,5:#smt:(rpow_gt0 b2r_ge0). |
| 166 | + rewrite !cell_eq_upto_split 1,2:/#. |
| 167 | + rewrite !get_set //= 1,2:#smt:(mul_add_lt). |
| 168 | + case (a0.[i{hr} * m{hr} + j{hr}]) => Hcase /=. |
| 169 | + + rewrite -row_eq_upto_unrelated_set 1:#smt:(mul_add_lt). |
| 170 | + rewrite -cell_eq_upto_unrelated_set 1:#smt:(mul_add_lt). |
| 171 | + by smt(rpow1 rpowN rpowD). |
| 172 | + + rewrite /= -row_eq_upto_unrelated_set 1:#smt:(mul_add_lt). |
| 173 | + rewrite -cell_eq_upto_unrelated_set 1:#smt:(mul_add_lt). |
| 174 | + by smt(rpow1 rpowN rpowD). |
| 175 | + (* pre => inv *) |
| 176 | + + wp; skip. |
| 177 | + move => &hr />. |
| 178 | + rewrite xle_cxr_r => *. |
| 179 | + rewrite xle_cxr_l 1:/#. |
| 180 | + rewrite (_: cell_eq_upto i{hr} 0 m{hr} a{hr} a0 = true) //= 1:/#. |
| 181 | +wp. |
| 182 | +skip => /> &hr. |
| 183 | +rewrite xle_cxr_r => *. |
| 184 | +rewrite xle_cxr_l 1:/#. |
| 185 | +rewrite fromintN rpowN //= rpow_int //=. |
| 186 | +rewrite (_: row_eq_upto 0 m{hr} a{hr} a0 = true) //= 1:/#. |
| 187 | +qed. |
0 commit comments