Coverage for src\pqlattice\lattice\_reductions.py: 80%
41 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-01-06 01:25 +0100
« prev ^ index » next coverage.py v7.11.0, created at 2026-01-06 01:25 +0100
1from fractions import Fraction
3import numpy as np
5from .._utils import as_integer
6from ..typing import SquareMatrix, validate_aliases
7from ._gso import gso, project_coeffs
10@validate_aliases
11def lll(lattice_basis: SquareMatrix, delta: float = 0.99) -> SquareMatrix:
12 rows, _ = lattice_basis.shape
13 B = as_integer(lattice_basis)
14 while True:
15 B_star, _ = gso(B)
16 # Reduction Step
17 for i in range(1, rows):
18 for j in range(i - 1, -1, -1):
19 c_ij = round(project_coeffs(B_star[j], B[i]))
20 assert isinstance(c_ij, int)
21 B[i] = B[i] - c_ij * B[j]
22 # Swap step
23 exists = False
24 for i in range(rows - 1):
25 u = project_coeffs(B_star[i], B[i + 1])
26 r = u * B_star[i] + B_star[i + 1]
27 if delta * np.dot(B_star[i], B_star[i]) > np.dot(r, r):
28 B[[i, i + 1]] = B[[i + 1, i]]
29 exists = True
30 break
31 if not exists:
32 break
33 return B
36@validate_aliases
37def is_size_reduced(lattice_basis: SquareMatrix) -> bool:
38 _, U = gso(lattice_basis)
39 return bool(np.all(np.triu(U, 1) <= Fraction(1, 2)))
42@validate_aliases
43def lovasz_condition(lattice_basis: SquareMatrix, delta: float) -> bool:
44 norm2 = lambda a: np.sum(a * a, axis=1) # type: ignore
45 G, U = gso(lattice_basis)
46 lhs = delta * norm2(G[:-1])
47 rhs = norm2(G[1:] + np.diag(U, 1)[:, np.newaxis] * G[:-1])
48 return bool(np.all(lhs <= rhs))
51@validate_aliases
52def is_lll_reduced(lattice_basis: SquareMatrix, delta: float = 0.99) -> bool:
53 return is_size_reduced(lattice_basis) and lovasz_condition(lattice_basis, delta)