Coverage for src\pqlattice\lattice\_lattice.py: 95%

42 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-01-11 23:45 +0100

1import math 

2from functools import reduce 

3 

4import numpy as np 

5 

6from .._utils import as_integer 

7from ..linalg._linalg import det 

8from ..linalg._utils import norm2, per_row_norm 

9from ..typing import SquareMatrix, Vector, validate_aliases 

10 

11 

12@validate_aliases 

13def volume(lattice_basis: SquareMatrix) -> int: 

14 """_summary_ 

15 

16 Parameters 

17 ---------- 

18 lattice_basis : SquareMatrix 

19 _description_ 

20 

21 Returns 

22 ------- 

23 int 

24 _description_ 

25 """ 

26 return abs(det(lattice_basis)) 

27 

28 

29@validate_aliases 

30def rank(lattice_basis: SquareMatrix) -> int: 

31 """_summary_ 

32 

33 Parameters 

34 ---------- 

35 lattice_basis : SquareMatrix 

36 _description_ 

37 

38 Returns 

39 ------- 

40 int 

41 _description_ 

42 """ 

43 return lattice_basis.shape[0] 

44 

45 

46@validate_aliases 

47def discriminant(lattice_basis: SquareMatrix) -> int: 

48 """_summary_ 

49 

50 Parameters 

51 ---------- 

52 lattice_basis : SquareMatrix 

53 _description_ 

54 

55 Returns 

56 ------- 

57 int 

58 _description_ 

59 """ 

60 v = volume(lattice_basis) 

61 return v * v 

62 

63 

64@validate_aliases 

65def hadamard_ratio(lattice_basis: SquareMatrix) -> float: 

66 """_summary_ 

67 

68 Parameters 

69 ---------- 

70 lattice_basis : SquareMatrix 

71 _description_ 

72 

73 Returns 

74 ------- 

75 float 

76 _description_ 

77 """ 

78 return (volume(lattice_basis) / reduce(lambda a, b: a * b, per_row_norm(lattice_basis))) ** (1 / rank(lattice_basis)) 

79 

80 

81@validate_aliases 

82def gaussian_heuristic(lattice_basis: SquareMatrix) -> float: 

83 """_summary_ 

84 

85 Parameters 

86 ---------- 

87 lattice_basis : SquareMatrix 

88 _description_ 

89 

90 Returns 

91 ------- 

92 float 

93 _description_ 

94 """ 

95 n = rank(lattice_basis) 

96 return math.sqrt(n / (2 * math.pi * math.e)) * (volume(lattice_basis) ** (1 / n)) 

97 

98 

99@validate_aliases 

100def glr_2dim(lattice_basis: SquareMatrix) -> SquareMatrix: 

101 """_summary_ 

102 

103 Parameters 

104 ---------- 

105 lattice_basis : SquareMatrix 

106 _description_ 

107 

108 Returns 

109 ------- 

110 SquareMatrix 

111 _description_ 

112 

113 Raises 

114 ------ 

115 ValueError 

116 _description_ 

117 """ 

118 if lattice_basis.shape != (2, 2): 

119 raise ValueError("Lattice has to have rank 2 for gaussian reduction") 

120 

121 w1: Vector = lattice_basis[0] 

122 w2: Vector = lattice_basis[1] 

123 

124 v1 = w1.astype(float) 

125 v2 = w2.astype(float) 

126 if norm2(v1) > norm2(v2): 

127 v1, v2 = v2, v1 

128 

129 while norm2(v2) > norm2(v1): 

130 m = np.rint(np.dot(v1, v2) / np.dot(v1, v1)) 

131 if m == 0: 

132 return as_integer([v1, v2]) 

133 v2 = v2 - m * v1 

134 if norm2(v1) > norm2(v2): 

135 v1, v2 = v2, v1 

136 

137 return np.array([v1, v2])