|
1 | 1 | """
|
2 |
| -# PLM(Python Lattice Module) |
| 2 | +# PLL(Python Lattice Library) |
3 | 3 |
|
4 | 4 | PLM(official name: Python Lattice Module) is a module for lattices.
|
5 | 5 |
|
@@ -245,6 +245,77 @@ def LLL(self, delta: float = 0.99) -> np.ndarray:
|
245 | 245 | return self.basis
|
246 | 246 |
|
247 | 247 |
|
| 248 | + def MLLL(self, delta: float = 0.99) -> np.ndarray: |
| 249 | + """LLL-reduction. |
| 250 | +
|
| 251 | + Args: |
| 252 | + delta (float, optional): Reduction parameter. Defaults to 0.99. |
| 253 | +
|
| 254 | + Returns: |
| 255 | + np.ndarray: LLL-reduced basis matrix. |
| 256 | + """ |
| 257 | + z = self.nrows - 1; g = 0 |
| 258 | + while g <= z: |
| 259 | + if np.all(self.basis[g] == 0): |
| 260 | + if g < z: |
| 261 | + self.basis[g], self.basis[z] = np.copy(self.basis[z]), np.copy(self.basis[g]) |
| 262 | + z -= 1 |
| 263 | + self.basis_star = self.basis[g] |
| 264 | + for j in range(g): |
| 265 | + self.mu[g, j] = np.dot(self.basis[g], self.basis_star[j]) / self.B[j] |
| 266 | + self.basis_star[g] -= self.mu[g, j] * np.copy(self.basis_star[j]) |
| 267 | + self.B[g] = np.dot(self.basis_star[g], self.basis_star[g]) |
| 268 | + self.mu[g, g] = 1. |
| 269 | + if g == 0: |
| 270 | + g = 1 |
| 271 | + else: |
| 272 | + l = g; k = g; startagain = False |
| 273 | + while k <= l and (not startagain): |
| 274 | + if abs(self.mu[k, k - 1]) > 0.5: |
| 275 | + q = round(self.mu[k, k - 1]) |
| 276 | + self.basis[k] -= q * np.copy(self.basis[k - 1]) |
| 277 | + self.mu[k, : k] -= q * np.copy(self.mu[k - 1, : k]) |
| 278 | + nu = self.mu[k, k - 1] |
| 279 | + B = self.B[k] + nu * nu * self.B[k - 1] |
| 280 | + if B >= delta * self.B[k - 1]: |
| 281 | + for j in range(k - 1)[::-1]: |
| 282 | + if abs(self.mu[k, j]) > 0.5: |
| 283 | + q = round(self.mu[k, j]) |
| 284 | + self.basis[k] -= q * np.copy(self.basis[j]) |
| 285 | + self.mu[k, : j + 1] -= q * np.copy(self.mu[j, : j + 1]) |
| 286 | + k += 1 |
| 287 | + else: |
| 288 | + if np.all(self.basis[k] == 0): |
| 289 | + if k < z: |
| 290 | + self.basis[z], self.basis[k] = np.copy(self.basis[k]), np.copy(self.basis[z]) |
| 291 | + z -= 1; g = k; startagain = True |
| 292 | + else: |
| 293 | + self.basis[k - 1], self.basis[k] = np.copy(self.basis[k]), np.copy(self.basis[k - 1]) |
| 294 | + self.mu[k, : k - 1], self.mu[k - 1, : k - 1] = np.copy(self.mu[k - 1, : k - 1]), np.copy(self.mu[k, : k - 1]) |
| 295 | + if B != 0: |
| 296 | + if self.B[k] == 0: |
| 297 | + self.B[k - 1] = B |
| 298 | + self.basis_star[k - 1] *= nu |
| 299 | + self.mu[k, k - 1] = 1. / nu |
| 300 | + else: |
| 301 | + t = self.B[k - 1] / B; self.mu[k, k - 1] = nu * t |
| 302 | + w = np.copy(self.basis[k - 1]); self.basis[k - 1] = np.copy(self.basis[k]) + nu * np.copy(w) |
| 303 | + self.B[k - 1] = B |
| 304 | + if k <= l: |
| 305 | + self.basis_star[k] = -self.mu[k, k - 1] * np.copy(self.basis_star[k]) + (self.B[k] / B) * np.copy(w) |
| 306 | + t = np.copy(self.mu[k + 1: l + 1, k]) |
| 307 | + self.mu[k + 1: l + 1, k] = np.copy(self.mu[k + 1: l + 1, k - 1]) - nu * np.copy(t) |
| 308 | + self.mu[k + 1: l + 1, k - 1] = np.copy(t) + self.mu[k, k - 1] * np.copy(self.mu[k + 1: l + 1, k]) |
| 309 | + else: |
| 310 | + self.B[k], self.B[k - 1] = self.B[k - 1], self.B[k] |
| 311 | + self.basis_star[k], self.basis_star[k - 1] = self.basis_star[k - 1], self.basis_star[k] |
| 312 | + self.mu[k + 1: l + 1, k], self.mu[k + 1: l + 1, k - 1] = np.copy(self.mu[k + 1: l + 1, k - 1]), np.copy(self.mu[k + 1: l + 1, k]) |
| 313 | + k = max(k - 1, 2) |
| 314 | + if not startagain: |
| 315 | + g += 1 |
| 316 | + return self.basis |
| 317 | + |
| 318 | + |
248 | 319 | def DeepLLL(self, delta : float = 0.99) -> np.ndarray:
|
249 | 320 | """Deep-LLL-reduction (algorithm is from C.P.Schnorr and M. Euchner(1994)).
|
250 | 321 |
|
|
0 commit comments