12
12
import numpy as np
13
13
import sys
14
14
15
+
15
16
class lattice ():
16
- def __init__ (self , b : np .ndarray , n : int , m : int ):
17
- self .basis = np .copy (b )
17
+ def __init__ (self , b : np .ndarray , n : int , m : int , dtype = None ):
18
+ self .basis = np .copy (np . array ( b , dtype = dtype ) )
18
19
self .nrows = n
19
20
self .ncols = m
20
21
self .mu = np .zeros ((n , n ))
21
22
self .basis_star = np .zeros ((n , m ))
22
23
self .B = np .zeros (n )
23
24
24
- def __init__ (self , b : np .ndarray ):
25
+ def __init__ (self , b : np .ndarray , dtype = None ):
25
26
n , m = b .shape
26
- self .basis = np .copy (b )
27
+ self .basis = np .copy (np . array ( b , dtype = dtype ) )
27
28
self .nrows = n
28
29
self .ncols = m
29
30
self .mu = np .eye (n )
@@ -34,7 +35,9 @@ def __init__(self, b: np.ndarray):
34
35
def print (self ):
35
36
"""Prints lattice basis.
36
37
"""
37
- print (self .basis )
38
+ print (f"Basis =\n { self .basis } " )
39
+ print (f"Rank = { self .nrows } " )
40
+ print (f"Volume = { self .vol ()} " )
38
41
39
42
40
43
def vol (self ) -> float :
@@ -243,77 +246,6 @@ def LLL(self, delta: float = 0.99) -> np.ndarray:
243
246
self .mu [k + 1 : self .nrows , k - 1 ] = np .copy (t ) + self .mu [k , k - 1 ] * np .copy (self .mu [k + 1 : self .nrows , k ])
244
247
k = max (k - 1 , 1 )
245
248
return self .basis
246
-
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
249
318
250
319
251
def DeepLLL (self , delta : float = 0.99 ) -> np .ndarray :
@@ -615,4 +547,46 @@ def __init__(self, n: int):
615
547
lattice .mu = np .eye (n )
616
548
lattice .basis_star = np .zeros ((n , n ))
617
549
lattice .B = np .zeros (n )
618
-
550
+
551
+
552
+ def HermiteConstat (n : int ) -> float :
553
+ """Return Hermite constant
554
+
555
+ Args:
556
+ n (int): Rank of lattice.
557
+
558
+ Returns:
559
+ float: n-th Hermite's constant
560
+ """
561
+ if n == 1 :
562
+ return 1
563
+ elif n == 2 :
564
+ return 2 / np .sqrt (3 )
565
+ elif n == 3 :
566
+ return np .cbrt (2 )
567
+ elif n == 4 :
568
+ return np .sqrt (2 )
569
+ elif n == 5 :
570
+ return 8 ** (1. / 5. )
571
+ elif n == 6 :
572
+ return (64. / 3. ) ** (1. / 6. )
573
+ elif n == 7 :
574
+ return 64 ** (1. / 7. )
575
+ elif n == 8 :
576
+ return 2
577
+ elif n == 24 :
578
+ return 4
579
+ else :
580
+ sys .exit (f"Rank Error: { n } -th Hermite's constant is not shown." )
581
+
582
+
583
+ def Hermite_constant (n : int ) -> float :
584
+ """Other name of the function HermiteConstant
585
+
586
+ Args:
587
+ n (int): Rank of lattice.
588
+
589
+ Returns:
590
+ float: n-th Hermite constant
591
+ """
592
+ return HermiteConstat (n )
0 commit comments