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

1 import math

2 from functools import reduce

3

4 import numpy as np

5

6 from .._utils import as_integer

7 from ..linalg._linalg import det

8 from ..linalg._utils import norm2, per_row_norm

9 from ..typing import SquareMatrix, Vector, validate_aliases

10

11

12@validate_aliases

13 def 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

30 def 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

47 def 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

65 def 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

82 def 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

100 def 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])