Skip to content

Commit 018ae48

Browse files
committed
色々と修正
1 parent ca940b3 commit 018ae48

File tree

2 files changed

+36
-56
lines changed

2 files changed

+36
-56
lines changed

PLM.py

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
"""
1111

1212
import numpy as np
13-
import sympy
1413
import sys
1514

1615
class lattice():
@@ -56,6 +55,19 @@ def volume(self) -> float:
5655
return np.sqrt(np.linalg.det(self.basis * self.basis.T))
5756

5857

58+
def dual(self):
59+
"""Computes dual-lattice.
60+
61+
Returns:
62+
lattice: Dual-lattice.
63+
"""
64+
c = lattice(self.basis)
65+
self.basis_star, self.mu = self.GSO()
66+
c.basis = np.matmul(np.matmul(np.linalg.inv(self.mu.T), np.linalg.inv(np.matmul(self.basis_star, self.basis_star.T))), self.basis_star)
67+
c.basis_star, c.mu = c.GSO()
68+
return c
69+
70+
5971
def GSO(self, mode: str = "normal") -> np.ndarray:
6072
"""Gram-Schmidt's method.
6173
@@ -82,7 +94,6 @@ def GSO(self, mode: str = "normal") -> np.ndarray:
8294
self.basis_star[i] -= self.mu[i, j] * np.copy(self.basis_star[j])
8395
if mode == "square" or mode == "both":
8496
self.B[i] = np.dot(self.basis_star[i], self.basis_star[i])
85-
8697
if mode == "normal":
8798
return self.basis_star, self.mu
8899
elif mode == "square":
@@ -171,7 +182,7 @@ def Gauss(self) -> np.ndarray:
171182

172183

173184
def Lagrange(self) -> np.ndarray:
174-
"""Lagrange reduction
185+
"""Lagrange reduction. This is other name of Gauss().
175186
176187
Returns:
177188
np.ndarray: Lagrange reduced lattice basis matrix.
@@ -199,15 +210,13 @@ def LLL(self, delta: float = 0.99) -> np.ndarray:
199210
np.ndarray: LLL-reduced basis
200211
"""
201212
self.B, self.mu = self.GSO(mode = "square")
202-
203213
k = 1
204214
while k < self.nrows:
205215
for j in range(k)[::-1]:
206216
if abs(self.mu[k, j]) > 0.5:
207217
q = round(self.mu[k, j])
208218
self.basis[k] -= q * np.copy(self.basis[j])
209219
self.mu[k, : j + 1] -= q * np.copy(self.mu[j, : j + 1])
210-
211220
if self.B[k] >= (delta - self.mu[k, k - 1] * self.mu[k, k - 1]) * self.B[k - 1]:
212221
k += 1
213222
else:
@@ -257,8 +266,19 @@ def DeepLLL(self, delta : float = 0.99) -> np.ndarray:
257266
self.B, self.mu = self.GSO(mode = "square")
258267
k = max(i - 1, 0)
259268
k += 1
260-
261269
return self.basis
270+
271+
272+
def DEEP(self, delta: float = 0.99) -> np.ndarray:
273+
"""Other name of DeepLLL().
274+
275+
Args:
276+
delta (float, optional): Reduction parameter. Defaults to 0.99.
277+
278+
Returns:
279+
np.ndarray: Deep-LLL-reduced lattice basis matrix.
280+
"""
281+
return self.DeepLLL(delta = delta)
262282

263283

264284
def PotLLL(self, delta: float = 0.99) -> np.ndarray:
@@ -281,8 +301,7 @@ def PotLLL(self, delta: float = 0.99) -> np.ndarray:
281301
self.mu[l, : j + 1] -= q * np.copy(self.mu[j, : j + 1])
282302
P = P_min = 1.; k = 0
283303
for j in range(l)[::-1]:
284-
S = np.sum(self.mu[l, j: l] * self.mu[l, j: l] * self.B[j: l])
285-
P *= (self.B[l] + S) / self.B[j]
304+
P *= (self.B[l] + np.sum(self.mu[l, j: l] * self.mu[l, j: l] * self.B[j: l])) / self.B[j]
286305
if P < P_min: k = j; P_min = P
287306
if delta > P_min:
288307
t = np.copy(self.basis[l])
@@ -370,7 +389,7 @@ def _ENUM_(mu: np.ndarray, B: np.ndarray, n: int, delta: float) -> np.ndarray:
370389
w[k] = 1
371390
else:
372391
k += 1
373-
if k == n: return np.zeros(n, int)
392+
if k == n: return None
374393
r[k - 1] = k
375394
if k >= last_nonzero:
376395
last_nonzero = k
@@ -386,7 +405,7 @@ def _ENUM_(mu: np.ndarray, B: np.ndarray, n: int, delta: float) -> np.ndarray:
386405
while True:
387406
pre_ENUM_v = np.copy(ENUM_v)
388407
ENUM_v = _ENUM_(self.mu, self.B, self.nrows, delta)
389-
if np.all(ENUM_v == 0): return pre_ENUM_v
408+
if ENUM_v is None: return np.matmul(pre_ENUM_v, self.basis)
390409
delta *= 0.99
391410

392411

@@ -417,45 +436,6 @@ def project_basis(self, k: int, l: int) -> np.ndarray:
417436
return pi_b
418437

419438

420-
def BKZ(self, beta: int, delta: float = 0.99) -> np.ndarray:
421-
"""BKZ-reduces a lattice basis matrix(algorithm is from C. P. Schnorr and M. Euchner(1994)).
422-
423-
Now this function is very unstable.
424-
425-
Args:
426-
beta (int): Block size.
427-
delta (float, optional): Reduction parameter. Defaults to 0.99.
428-
429-
Returns:
430-
np.ndarray: BKZ-reduced basis matirx.
431-
"""
432-
self.basis = self.LLL(delta = delta)
433-
z = k = 0
434-
while z < self.nrows - 2:
435-
print(z)
436-
if k == self.nrows - 1: k = 0
437-
k1 = k; k += 1
438-
l = min(k1 + beta, self.nrows); h = min(l + 1, self.nrows)
439-
self.B, self.mu = self.GSO(mode = "square")
440-
p = lattice(self.basis[k1: l, k1: l])
441-
w = p.ENUM_SVP(); s = w @ self.project_basis(k1, l - 1)
442-
if (not np.all(s == 0)) and self.B[k1] > np.dot(s, s):
443-
z = 0
444-
c = lattice(np.zeros((h + 1, self.ncols)))
445-
c.basis[: k1] = np.copy(self.basis[: k1])
446-
c.basis[k1] = w @ self.basis[k1: l]
447-
c.basis[k: h + 1] = np.copy(self.basis[k1: h])
448-
_, inds = sympy.Matrix(c.basis).T.rref()
449-
c.basis = np.copy(c.basis[np.array(inds)]); c.nrows = h
450-
c.basis = c.LLL(delta = delta)
451-
self.basis[: h] = np.copy(c.basis)
452-
else:
453-
z += 1
454-
c = lattice(self.basis[: h])
455-
self.basis[: h] = c.LLL(delta = delta)
456-
return self.basis
457-
458-
459439
def Babai(self, w: np.ndarray):
460440
"""Computes an approximate solution of CVP for target w using Babai's nearest plane algorithm(algorithm is from L. Babai(1986)).
461441
@@ -519,7 +499,7 @@ def _ENUM_(mu: np.ndarray, B: np.ndarray, n: int, a: np.ndarray, R: float) -> np
519499
w[k] = 1
520500
else:
521501
k += 1
522-
if k == n: return np.zeros(n, int)
502+
if k == n: return None
523503
r[k - 1] = k
524504
if v[k] > c[k]: v[k] -= w[k]
525505
else: v[k] += w[k]
@@ -528,11 +508,11 @@ def _ENUM_(mu: np.ndarray, B: np.ndarray, n: int, a: np.ndarray, R: float) -> np
528508
self.B, self.mu = self.GSO(mode = "square")
529509
ENUM_v = np.zeros(self.nrows, int)
530510
babaivec = self.Babai(t); R = np.dot(babaivec - t, babaivec - t)
531-
a = t @ np.linalg.pinv(self.basis)
511+
a = np.matmul(t, np.linalg.pinv(self.basis))
532512
while True:
533513
pre_ENUM_v = np.copy(ENUM_v)
534514
ENUM_v = _ENUM_(self.mu, self.B, self.nrows, a, R)
535-
if np.all(ENUM_v == 0): return pre_ENUM_v @ self.basis
515+
if ENUM_v is None: return np.matmul(pre_ENUM_v, self.basis)
536516
R *= 0.99
537517

538518

main.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import sympy
44

55
def main():
6-
b = PLM.random_lattice(40)
6+
b = PLM.random_lattice(70)
77
print(b.basis)
8-
a = b.PotLLL()[0]; print(a, np.linalg.norm(a))
8+
#a = b.PotLLL()[0]; print(a, np.linalg.norm(a))
99
#a = PLM.lattice.ENUM(b); print(a @ b.basis, np.linalg.norm(a @ b.basis))
10-
#a = b.BKZ(15); print(a, np.linalg.norm(a[0]))
11-
t = np.random.randint(10, 20, size=40)
10+
t = np.random.randint(10, 20, size=70)
1211
print(t)
1312
print(b.ENUM_CVP(t))
13+
print(b.ENUM_SVP())
1414

1515

1616
if __name__ == '__main__':

0 commit comments

Comments
 (0)