Adèlic Matrix Factorization¶
Adèlic Matrix Factorization
This file implements the adèlic matrix factorization algorithms described in Chapter 8 of [Her2021].
The function factor_GLQhat()
implements Algorithm 8.4 of [Her2021], which
factors an adèlic matrix \(M \in GL_n(\hat{\QQ})\) as \(M = BA\) with
\(B \in GL_n(\hat{\ZZ})\) and \(A \in GL_n^+(\QQ)\).
The function factor_GSpQhat()
implements Algorithm 8.9 of [Her201], which
factors a general symplectic matrix \(M \in GSp_{2g}(\hat{\QQ})\) as \(M = BA\) with
\(B \in GSp_{2g}(\hat{\ZZ})\) and \(A \in GSp_{2g}^+(\QQ)\).
REFERENCES:
[Her2021] Mathé Hertogh, Computing with adèles and idèles, master’s thesis, Leiden University, 2021.
AUTHORS:
Mathé Hertogh (2021-07): initial version based on [Her2021]
-
adeles.matrix.
Omega
(g)¶ Return the matrix \(\Omega_{2g}\)
The matrix \(\Omega_{2g}\) is the \(2g \times 2g\)-matrix given in \(g \times g\)-blocks by \((0, 1; -1, 0)\).
EXAMPLES:
sage: Omega(3) [ 0 0 0 1 0 0] [ 0 0 0 0 1 0] [ 0 0 0 0 0 1] [-1 0 0 0 0 0] [ 0 -1 0 0 0 0] [ 0 0 -1 0 0 0]
-
adeles.matrix.
denominator
(M)¶ Return the denominator of the \(\hat{\QQ}\)-matrix
M
This is the least common multiple of the denominators of the entries of
M
.EXAMPLES:
sage: M = matrix(Qhat, [[Qhat(1, 7/6), Qhat(1/3, 6)], ....: [ Qhat(0, 12), Qhat(5, 18)]]) sage: denominator(M) 6
-
adeles.matrix.
denominator_matrix
(M)¶ Return the denominator matrix of the \(\hat{\QQ}\)-matrix
M
This is the diagonal matrix \(D\) with \(D_{jj}\) equal to to least common multiple of the denominators of the entries of the \(j\)-th column of
M
.EXAMPLES:
sage: M = matrix(Qhat, [[Qhat(1, 7/6), Qhat(1/3, 6)], ....: [ Qhat(0, 12), Qhat(5, 18)]]) sage: denominator_matrix(M) [6 0] [0 3]
-
adeles.matrix.
factor_GLQhat
(M, detM)¶ Factor the \(GL_n(\hat{\QQ})\)-matrix \(M\) as \(M = BA\) with \(B \in GL_n(\hat{\ZZ})\) and \(A \in GL_n^+(\QQ)\)
Here \(GL_n\) denotes the general linear group, i.e. the group of invertible \(n \times n\)-matrices. \(GL_n^+(\QQ)\) denotes the subgroup of \(GL_n(\QQ)\) of matrices with positive determinant.
INPUT:
M
– an \(n \times n\)-matrix over the ring of profinite \(\QQ\)-numbers having good precision with respect todetM
(cf.has_good_precision()
) and representing at least one element of \(GL_n(\hat{\QQ})\) of determinant \(d\) satisfying \(d\hat{\ZZ} = detM\hat{\ZZ}\).detM
– a positive rational number
OUTPUT:
A matrix \(A \in GL_n^+(\QQ)\) such that for every matrix \(N \in GL_n(\hat{\QQ})\) that \(M\) represents and satisfying \(\det(N)\hat{\ZZ} = detM \hat{\ZZ}\) we have \(N A^{-1} \in GL_n(\hat{\ZZ})\).
ALGORITHM:
We perform Algorithm 8.4 of [Her2021].
EXAMPLES:
Let \(I\) be the \(2 \times 2\)-identity matrix, i.e. \((1, 0; 0, 1)\). Let \(N \in GL_2(\hat{\QQ})\) be given by \(N_2 = (1, 0; 0, 2)\) and \(N_p = I\) for all odd \(p\) (where \(N_p\) denotes the projection of \(N\) to \(GL_2(\QQ_p)\)). Note that \(\det(N)\hat{\ZZ} = 2\hat{\ZZ}\). The following matrix
M
represents \(N\) and has good precision with respect to \(2\).sage: M = matrix([[Qhat(1, 2), Qhat(0, 2)], ....: [Qhat(0, 2), Qhat(0, 2)]]); M [1 mod 2 0 mod 2] [0 mod 2 0 mod 2] sage: has_good_precision(M, 2) True
This function returns the following \(A\):
sage: A = factor_GLQhat(M, 2); A [1 0] [0 2]
Now it is indeed the case that \(N A^{-1} \in GL_2(\hat{\ZZ})\): at \(2\) this matrix equals \(I\) and at every odd prime \(p\) it equals the inverse of \(A\) and we have \(A \in GL_2(\ZZ_p)\).
Next we let \(N \in GL_2(\hat{\QQ})\) at \(2\) be given by
sage: N_2 = matrix(QQ, [[1, 0], [0, 1/4]]); N_2 [ 1 0] [ 0 1/4]
and at \(3\) by
sage: N_3 = matrix(QQ, [[0, 2], [3, 1/5]]); N_3 [ 0 2] [ 3 1/5]
and at the other primes by \(N_p = I\). In this case we have \(\det(N)\hat{\ZZ} = 3/4\hat{\ZZ}\). A matrix representing \(N\) and having good precision with respect to \(3/4\) is:
sage: M = matrix([[Qhat(21, 60), Qhat(20, 60)], ....: [Qhat(0, 60), Qhat(209/4, 60)]]); M [ 21 mod 60 20 mod 60] [ 0 mod 60 209/4 mod 60] sage: has_good_precision(M, 3/4) True
We obtain the following \(A \in GL_2^+(\QQ)\):
sage: A = factor_GLQhat(M, 3/4); A [ 3 0] [ 0 1/4]
We check that this is correct by checking that \(N_p A^{-1} \in GL_2(\ZZ_p)\) for all prime numbers \(p\). This is clear for \(p \geq 5\) since we then have \(I, A \in GL_2(\ZZ_p)\). At \(2\) and \(3\) we have
sage: N_2 * ~A, N_3 * ~A ( [1/3 0] [ 0 8] [ 0 1], [ 1 4/5] )
which indeed lie in \(GL_2(\ZZ_2)\) and \(GL_3(\ZZ_3)\) respectively.
Let’s do an example with \(n=3\); consider \(N \in GL_3(\hat{\QQ})\) given at \(3\) by
sage: N_3 = matrix(QQ, [[14, 1/3, 1], [7, 2, 0], [5, 3, 2/3]]); N_3 [ 14 1/3 1] [ 7 2 0] [ 5 3 2/3]
and at \(5\) by
sage: N_5 = matrix(QQ, [[15, 5, 0], [9, 11, -1], [5, -9, 1]]); N_5 [15 5 0] [ 9 11 -1] [ 5 -9 1]
and at all other primes \(p\) by the \(3 \times 3\)-identity matrix \(I\). We have
sage: det(N_3).valuation(3), det(N_5).valuation(5) (-2, 1)
and so \(det(N) \hat{\ZZ} = 5/9\hat{\ZZ}\). The following matrix represents \(N\) and has good precision with respect to \(5/9\):
sage: M = matrix([[Qhat([Qp(3)(N_3[i,j], 0), Qp(5)(N_5[i,j], 1)]) ....: for j in range(3)] for i in range(3)]) sage: M [ 0 mod 5 10/3 mod 5 0 mod 5] [ 4 mod 5 1 mod 5 4 mod 5] [ 0 mod 5 1 mod 5 8/3 mod 5] sage: has_good_precision(M, 5/9) True
Hence we compute:
sage: A = factor_GLQhat(M, 5/9); A [ 1 0 1/3] [ 0 1/3 1/3] [ 0 0 5/3]
and we check correctness by checking that \(N_3 A^{-1} \in GL_3(\ZZ_3)\) and \(N_5 A^{-1} \in GL_5(\ZZ_5)\):
sage: N_3 * ~A, N_5 * ~A ( [ 14 1 -12/5] [ 15 15 -6] [ 7 6 -13/5] [ 9 33 -9] [ 5 9 -12/5], [ 5 -27 5] ) sage: det(N_3*~A).valuation(3) == 0 True sage: det(N_5*~A).valuation(5) == 0 True
If the matrix does not have good precision, we throw an exception.
sage: M = matrix([[Qhat(1,2), Qhat(0,2)], [Qhat(0, 2), Qhat(0,2)]]) sage: factor_GLQhat(M, 4) Traceback (most recent call last): ... ValueError: matrix precision too low!
-
adeles.matrix.
factor_GSpQhat
(M, detM)¶ Factor the \(GSp_{2g}(\hat{\QQ})\)-matrix \(M\) as \(M = BA\) with \(B \in GSp_{2g}(\hat{\ZZ})\) and \(A \in GSp_{2g}^+(\QQ)\)
Here \(GSp_{2g}(R)\) denotes the general symplectic group over the ring \(R\) and \(GSp_{2g}^+(\QQ)\) denotes the subgroup of matrcies with positive mulitplier. See Chapter 8 of [Her2021] for details.
INPUT:
M
– a matrix over the ring of profinite \(\QQ\)-numbers having good precision with respect todetM
(cf.has_good_precision()
) and representing at least one element in \(GSp_{2g}(\hat{\QQ})\) of determinant \(d\) satisfying \(d\hat{\ZZ} = detM\hat{\ZZ}\)detM
– a positive rational number
OUTPUT:
A matrix \(A \in GSp_{2g}^+(\QQ)\) such that for every matrix \(N \in GSp_{2g}(\hat{\QQ})\) that \(M\) represents and satisfying \(\det(N)\hat{\ZZ} = detM \hat{\ZZ}\) we have \(N A^{-1} \in GSp_{2g}(\hat{\ZZ})\).
ALGORITHM:
We perform Algorithm 8.9 of [Her2021].
EXAMPLES:
Consider the following symplectic matrix over \(\QQ\):
sage: I = identity_matrix(2) sage: S = matrix([[1, 2], [2, 3]]) sage: N_2 = block_matrix([[I, S], [0*I, 1/2*I]], subdivide=False); N_2 [ 1 0 1 2] [ 0 1 2 3] [ 0 0 1/2 0] [ 0 0 0 1/2] sage: N_2.transpose() * Omega(2) * N_2 == 1/2 * Omega(2) True
It has multiplier \(1/2\) and hence determinant \(1/4\). Now consider the matrix \(N \in GSp_4(\hat{\QQ})\) given at \(2\) by \(N_2\) and at all other primes by the \(4 \times 4\)-identity matrix. We have \(\det(N)\hat{\ZZ} = 1/4\hat{\ZZ}\).
The following matrix represents \(N\) and has good precision with respect to \(1/4\):
sage: z = Qhat(0, 2) sage: e = Qhat(1, 2) sage: h = Qhat(1/2, 2) sage: M = matrix([[e,z,e,z],[z,e,z,e],[z,z,h,z],[z,z,z,h]]); M [ 1 mod 2 0 mod 2 1 mod 2 0 mod 2] [ 0 mod 2 1 mod 2 0 mod 2 1 mod 2] [ 0 mod 2 0 mod 2 1/2 mod 2 0 mod 2] [ 0 mod 2 0 mod 2 0 mod 2 1/2 mod 2] sage: has_good_precision(M, 1/4) True
Hence we can compute:
sage: A = factor_GSpQhat(M, 1/4); A [ 1 0 0 0] [ 0 1 0 0] [ 0 0 1/2 0] [ 0 0 0 1/2]
Then indeed \(A\) is symplectic:
sage: A.transpose() * Omega(2) * A == 1/2 * Omega(2) True
and for every odd prime number \(p\) we have \(A \in GSp_4(\ZZ_p)\). Hence to check that \(N A^{-1} \in GSp_4(\hat{\ZZ})\) is suffices to check that \(N_2 A^{-1} \in GSp_4(\ZZ_2)\):
sage: N_2 * ~A [1 0 2 4] [0 1 4 6] [0 0 1 0] [0 0 0 1] sage: det(N_2*~A) 1
Let’s now do a bigger example. We construct two rational symplectic matrices
sage: I = identity_matrix(3) sage: S = matrix([[1/2, 1, 2], [1, 2, 3], [2, 3, 1/5]]) sage: N_2 = block_matrix([[6*I, S], [0*I, 2*I]], subdivide=False); N_2 [ 6 0 0 1/2 1 2] [ 0 6 0 1 2 3] [ 0 0 6 2 3 1/5] [ 0 0 0 2 0 0] [ 0 0 0 0 2 0] [ 0 0 0 0 0 2] sage: N_2.transpose() * Omega(3) * N_2 == 12 * Omega(3) True
and
sage: U = matrix([[3, 2, 1/2], [1, -3, -3], [4, -2, 5]]) sage: X = block_matrix([[I, 0*I], [S, 1/3*I]], subdivide=False) sage: Y = block_matrix([[U, 0*I], [0*I, ~U.transpose()]], subdivide=False) sage: N_3 = X*Y; N_3 [ 3 2 1/2 0 0 0] [ 1 -3 -3 0 0 0] [ 4 -2 5 0 0 0] [ 21/2 -6 29/4 7/92 17/276 -5/138] [ 17 -10 19/2 11/276 -13/276 -7/138] [ 49/5 -27/5 -7 3/184 -19/552 11/276] sage: N_3.transpose() * Omega(3) * N_3 == 1/3 * Omega(3) True
We let \(N \in GSp_6(\hat{\QQ})\) at \(2\) be given by \(N_2\), at \(3\) by \(N_3\) and by the identity matrix at all other primes. Then because we have
sage: det(N_2).valuation(2) 6 sage: det(N_3).valuation(3) -3
the determinant of \(N\) satisfies \(det(N)\hat{\ZZ} = 64/27\hat{\ZZ}\).
We construct a representation \(M\) of \(N\) of good precision:
sage: M = matrix([[Qhat([Qp(2)(N_2[i,j], 7), Qp(3)(N_3[i,j], 1)]) ....: for j in range(6)] for i in range(6)]) sage: M [ 6 mod 384 128 mod 384 128 mod 384 513/2 mod 384 129 mod 384 258 mod 384] [ 256 mod 384 6 mod 384 0 mod 384 129 mod 384 258 mod 384 3 mod 384] [ 256 mod 384 256 mod 384 134 mod 384 258 mod 384 3 mod 384 333 mod 384] [ 0 mod 384 0 mod 384 128 mod 384 2 mod 384 256/3 mod 384 256/3 mod 384] [ 128 mod 384 128 mod 384 128 mod 384 640/3 mod 384 646/3 mod 384 128/3 mod 384] [ 128 mod 384 0 mod 384 128 mod 384 0 mod 384 128/3 mod 384 262/3 mod 384] sage: has_good_precision(M, 64/27) True
Now we can use this factorization function:
sage: A = factor_GSpQhat(M, 64/27); A [ 2 0 0 1/6 1/3 0] [ 0 2 0 1/3 0 1/3] [ 0 0 2 0 1/3 1/3] [ 0 0 0 2/3 0 0] [ 0 0 0 0 2/3 0] [ 0 0 0 0 0 2/3]
Let’s check that \(A\) does indeed lie in \(GSp_6^+(\QQ)\):
sage: A.transpose() * Omega(3) * A == 4/3 * Omega(3) True
From the entries of \(A\) and the fact that \(A\) has multiplier \(4/3\) it follows that \(A \in GSp_6(\ZZ_p)\) for all prime numbers bigger than \(3\). At the primes \(2\) and \(3\) we have
sage: min([entry.valuation(2) for entry in (N_2 * ~A).list()]) 0 sage: det(N_2*~A).valuation(2) 0 sage: min([entry.valuation(3) for entry in (N_3 * ~A).list()]) 0 sage: det(N_3*~A).valuation(3) 0
Therefore \(N A^{-1} \in GSp_6(\hat{\ZZ})\) as desired.
-
adeles.matrix.
has_good_precision
(M, Delta)¶ Return wether or not the sqaure matrix
M
overQhat
has good precision with respect toDelta
By \(M\) having good precision with respect to \(\Delta \in \QQ_{>0}\) we mean the following. Let \(D\) be the denominator matrix of \(M\) and let \(m\) be the precision (i.e. modulus) of \(MD\). Then \(M\) has good precision with respect to \(\Delta\) if for all prime numbers \(p\) we have \(ord_p(m) \geq ord_p(\Delta \det(D))\).
INPUT:
M
– a square matrix over the profinite \(\QQ\)-integersDelta
– a positive rational number
EXAMPLES:
sage: M = matrix([[Qhat(1/3, 10/7), Qhat(4, 20)], ....: [Qhat(1/5, 20/7), Qhat(5/3, 30)]]) sage: has_good_precision(M, 2/21) True sage: has_good_precision(M, 4/21) False sage: has_good_precision(M, 2/7) False sage: has_good_precision(M, 2/3) False sage: has_good_precision(M, 1/21) True
-
adeles.matrix.
matrix_modulo
(A, N)¶ Project a matrix over \(\hat{\ZZ}\) to a matrix over \(\ZZ/N\ZZ\)
INPUT:
A
– a matrix with entries integral elements of \(\hat{\QQ}\) and with modulus divisible byN
N
– an integer
-
adeles.matrix.
modulus
(M)¶ Return the modulus (i.e. precision) of the \(\hat{\QQ}\)-matrix
M
This is the greatest common divisor of the moduli of the entries of
M
.EXAMPLES:
sage: M = matrix(Qhat, [[Qhat(1, 7/6), Qhat(1/3, 6)], ....: [ Qhat(0, 12), Qhat(5, 18)]]) sage: modulus(M) 1/6
-
adeles.matrix.
value_matrix
(M)¶ Return the value matrix of the \(\hat{\QQ}\)-matrix
M
This is the matrix consisting of the values of the entries of
M
.EXAMPLES:
sage: M = matrix(Qhat, [[Qhat(1, 7/6), Qhat(1/3, 6)], ....: [ Qhat(0, 12), Qhat(5, 18)]]) sage: value_matrix(M) [ 1 1/3] [ 0 5]