1212import numpy as np
1313import sys
1414
15+
1516class 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 ) )
1819 self .nrows = n
1920 self .ncols = m
2021 self .mu = np .zeros ((n , n ))
2122 self .basis_star = np .zeros ((n , m ))
2223 self .B = np .zeros (n )
2324
24- def __init__ (self , b : np .ndarray ):
25+ def __init__ (self , b : np .ndarray , dtype = None ):
2526 n , m = b .shape
26- self .basis = np .copy (b )
27+ self .basis = np .copy (np . array ( b , dtype = dtype ) )
2728 self .nrows = n
2829 self .ncols = m
2930 self .mu = np .eye (n )
@@ -34,7 +35,9 @@ def __init__(self, b: np.ndarray):
3435 def print (self ):
3536 """Prints lattice basis.
3637 """
37- print (self .basis )
38+ print (f"Basis =\n { self .basis } " )
39+ print (f"Rank = { self .nrows } " )
40+ print (f"Volume = { self .vol ()} " )
3841
3942
4043 def vol (self ) -> float :
@@ -243,77 +246,6 @@ def LLL(self, delta: float = 0.99) -> np.ndarray:
243246 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 ])
244247 k = max (k - 1 , 1 )
245248 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
317249
318250
319251 def DeepLLL (self , delta : float = 0.99 ) -> np .ndarray :
@@ -615,4 +547,46 @@ def __init__(self, n: int):
615547 lattice .mu = np .eye (n )
616548 lattice .basis_star = np .zeros ((n , n ))
617549 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