Discriminant Groups
Torsion Quadratic Modules
A torsion quadratic module is the quotient $M/N$ of two quadratic integer lattices $N \subseteq M$ in the quadratic space $(V,\Phi)$. It inherits a bilinear form
\[b: M/N \times M/N \to \mathbb{Q} / n \mathbb{Z}\]
as well as a quadratic form
\[q: M/N \to \mathbb{Q} / m \mathbb{Z}.\]
where $n \mathbb{Z} = \Phi(M,N)$ and $m \mathbb{Z} = 2n\mathbb{Z} + \sum_{x \in N} \mathbb{Z} \Phi (x,x)$.
torsion_quadratic_module
— Methodtorsion_quadratic_module(M::ZZLat, N::ZZLat; gens::Union{Nothing, Vector{<:Vector}} = nothing,
snf::Bool = true,
modulus::QQFieldElem = QQFieldElem(0),
check::Bool = true) -> TorQuadModule
Given a Z-lattice $M$ and a sublattice $N$ of $M$, return the torsion quadratic module $M/N$.
If gens
is set, the images of gens
will be used as the generators of the abelian group $M/N$.
If snf
is true
, the underlying abelian group will be in Smith normal form. Otherwise, the images of the basis of $M$ will be used as the generators.
The underlying Type
TorQuadModule
— TypeTorQuadModule
Examples
julia> A = matrix(ZZ, [[2,0,0,-1],[0,2,0,-1],[0,0,2,-1],[-1,-1,-1,2]]);
julia> L = integer_lattice(gram = A);
julia> T = Hecke.discriminant_group(L)
Finite quadratic module
over integer ring
Abelian group: (Z/2)^2
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[ 1 1//2]
[1//2 1]
We represent torsion quadratic modules as quotients of $\mathbb{Z}$-lattices by a full rank sublattice.
We store them as a $\mathbb{Z}$-lattice M
together with a projection p : M -> A
onto an abelian group A
. The bilinear structure of A
is induced via p
, that is <a, b> = <p^-1(a), p^-1(a)>
with values in $\mathbb{Q}/n\mathbb{Z}$, where $n$ is the modulus and depends on the kernel of p
.
Elements of A are basically just elements of the underlying abelian group. To move between M
and A
, we use the lift
function lift : M -> A
and coercion A(m)
.
Examples
julia> R = rescale(root_lattice(:D,4),2);
julia> D = discriminant_group(R);
julia> A = abelian_group(D)
GrpAb: (Z/2)^2 x (Z/4)^2
julia> d = D[1]
Element
of finite quadratic module: (Z/2)^2 x (Z/4)^2 -> Q/2Z
with components [1 0 0 0]
julia> d == D(A(d))
true
julia> lift(d)
4-element Vector{QQFieldElem}:
1
1
3//2
1
N.B. Since there are no elements of $\mathbb{Z}$-lattices, we think of elements of M
as elements of the ambient vector space. Thus if v::Vector
is such an element then the coordinates with respec to the basis of M
are given by solve_left(basis_matrix(M), v)
.
Most of the functionality mirrors that of AbGrp
its elements and homomorphisms. Here we display the part that is specific to elements of torsion quadratic modules.
Attributes
abelian_group
— Methodabelian_group(T::TorQuadModule) -> GrpAbFinGen
Return the underlying abelian group of T
.
cover
— Methodcover(T::TorQuadModule) -> ZZLat
For $T=M/N$ this returns $M$.
relations
— Methodrelations(T::TorQuadModule) -> ZZLat
For $T=M/N$ this returns $N$.
value_module
— Methodvalue_module(T::TorQuadModule) -> QmodnZ
Return the value module Q/nZ
of the bilinear form of T
.
value_module_quadratic_form
— Methodvalue_module_quadratic_form(T::TorQuadModule) -> QmodnZ
Return the value module Q/mZ
of the quadratic form of T
.
gram_matrix_bilinear
— Methodgram_matrix_bilinear(T::TorQuadModule) -> QQMatrix
Return the gram matrix of the bilinear form of T
.
gram_matrix_quadratic
— Methodgram_matrix_quadratic(T::TorQuadModule) -> QQMatrix
Return the 'gram matrix' of the quadratic form of T
.
The off diagonal entries are given by the bilinear form whereas the diagonal entries are given by the quadratic form.
modulus_bilinear_form
— Methodmodulus_bilinear_form(T::TorQuadModule) -> QQFieldElem
Return the modulus of the value module of the bilinear form ofT
.
modulus_quadratic_form
— Methodmodulus_quadratic_form(T::TorQuadModule) -> QQFieldElem
Return the modulus of the value module of the quadratic form of T
.
Elements
quadratic_product
— Methodquadratic_product(a::TorQuadModuleElem) -> QmodnZElem
Return the quadratic product of a
.
It is defined in terms of a representative: for $b + M \in M/N=T$, this returns $\Phi(b,b) + n \mathbb{Z}$.
inner_product
— Methodinner_product(a::TorQuadModuleElem, b::TorQuadModuleElem) -> QmodnZElem
Return the inner product of a
and b
.
Lift to the cover
lift
— Methodlift(a::TorQuadModuleElem) -> Vector{QQFieldElem}
Lift a
to the ambient space of cover(parent(a))
.
For $a + N \in M/N$ this returns the representative $a$.
representative
— Methodrepresentative(a::TorQuadModuleElem) -> Vector{QQFieldElem}
For $a + N \in M/N$ this returns the representative $a$. An alias for lift(a)
.
Orthogonal submodules
orthogonal_submodule
— Methodorthogonal_submodule(T::TorQuadModule, S::TorQuadModule)-> TorQuadModule
Return the orthogonal submodule to the submodule S
of T
.
Isometry
is_isometric_with_isometry
— Methodis_isometric_with_isometry(T::TorQuadModule, U::TorQuadModule)
-> Bool, TorQuadModuleMor
Return whether the torsion quadratic modules T
and U
are isometric. If yes, it also returns an isometry $T \to U$.
If T
and U
are not semi-regular it requires that they both split into a direct sum of their respective quadratic radical (see radical_quadratic
).
It requires that both T
and U
have modulus 1: in case one of them do not, they should be rescaled (see rescale
).
Examples
julia> T = torsion_quadratic_module(QQ[2//3 2//3 0 0 0;
2//3 2//3 2//3 0 2//3;
0 2//3 2//3 2//3 0;
0 0 2//3 2//3 0;
0 2//3 0 0 2//3])
Finite quadratic module
over integer ring
Abelian group: (Z/3)^5
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[2//3 2//3 0 0 0]
[2//3 2//3 2//3 0 2//3]
[ 0 2//3 2//3 2//3 0]
[ 0 0 2//3 2//3 0]
[ 0 2//3 0 0 2//3]
julia> U = torsion_quadratic_module(QQ[4//3 0 0 0 0;
0 4//3 0 0 0;
0 0 4//3 0 0;
0 0 0 4//3 0;
0 0 0 0 4//3])
Finite quadratic module
over integer ring
Abelian group: (Z/3)^5
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[4//3 0 0 0 0]
[ 0 4//3 0 0 0]
[ 0 0 4//3 0 0]
[ 0 0 0 4//3 0]
[ 0 0 0 0 4//3]
julia> bool, phi = is_isometric_with_isometry(T,U)
(true, Map with following data
Domain:
=======
Finite quadratic module: (Z/3)^5 -> Q/2Z
Codomain:
=========
Finite quadratic module: (Z/3)^5 -> Q/2Z)
julia> is_bijective(phi)
true
julia> T2, _ = sub(T, [-T[4], T[2]+T[3]+T[5]])
(Finite quadratic module: (Z/3)^2 -> Q/2Z, Map with following data
Domain:
=======
Finite quadratic module: (Z/3)^2 -> Q/2Z
Codomain:
=========
Finite quadratic module: (Z/3)^5 -> Q/2Z)
julia> U2, _ = sub(T, [T[4], T[2]+T[3]+T[5]])
(Finite quadratic module: (Z/3)^2 -> Q/2Z, Map with following data
Domain:
=======
Finite quadratic module: (Z/3)^2 -> Q/2Z
Codomain:
=========
Finite quadratic module: (Z/3)^5 -> Q/2Z)
julia> bool, phi = is_isometric_with_isometry(U2, T2)
(true, Map with following data
Domain:
=======
Finite quadratic module: (Z/3)^2 -> Q/2Z
Codomain:
=========
Finite quadratic module: (Z/3)^2 -> Q/2Z)
julia> is_bijective(phi)
true
is_anti_isometric_with_anti_isometry
— Methodis_anti_isometric_with_anti_isometry(T::TorQuadModule, U::TorQuadModule)
-> Bool, TorQuadModuleMor
Return whether there exists an anti-isometry between the torsion quadratic modules T
and U
. If yes, it returns such an anti-isometry $T \to U$.
If T
and U
are not semi-regular it requires that they both split into a direct sum of their respective quadratic radical (see radical_quadratic
).
It requires that both T
and U
have modulus 1: in case one of them do not, they should be rescaled (see rescale
).
Examples
julia> T = torsion_quadratic_module(QQ[4//5;])
Finite quadratic module
over integer ring
Abelian group: Z/5
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[4//5]
julia> bool, phi = is_anti_isometric_with_anti_isometry(T, T)
(true, Map with following data
Domain:
=======
Finite quadratic module: Z/5 -> Q/2Z
Codomain:
=========
Finite quadratic module: Z/5 -> Q/2Z)
julia> a = gens(T)[1];
julia> a*a == -phi(a)*phi(a)
true
julia> G = matrix(FlintQQ, 6, 6 , [3 3 0 0 0 0;
3 3 3 0 3 0;
0 3 3 3 0 0;
0 0 3 3 0 0;
0 3 0 0 3 0;
0 0 0 0 0 10]);
julia> V = quadratic_space(QQ, G);
julia> B = matrix(QQ, 6, 6 , [1 0 0 0 0 0;
0 1//3 1//3 2//3 1//3 0;
0 0 1 0 0 0;
0 0 0 1 0 0;
0 0 0 0 1 0;
0 0 0 0 0 1//5]);
julia> M = lattice(V, B);
julia> B2 = matrix(FlintQQ, 6, 6 , [ 1 0 -1 1 0 0;
0 0 1 -1 0 0;
-1 1 1 -1 -1 0;
1 -1 -1 2 1 0;
0 0 -1 1 1 0;
0 0 0 0 0 1]);
julia> N = lattice(V, B2);
julia> T = torsion_quadratic_module(M, N)
Finite quadratic module
over integer ring
Abelian group: Z/15
Bilinear value module: Q/Z
Quadratic value module: Q/Z
Gram matrix quadratic form:
[3//5]
julia> bool, phi = is_anti_isometric_with_anti_isometry(T,T)
(true, Map with following data
Domain:
=======
Finite quadratic module: Z/15 -> Q/Z
Codomain:
=========
Finite quadratic module: Z/15 -> Q/Z)
julia> a = gens(T)[1];
julia> a*a == -phi(a)*phi(a)
true
Primary and elementary modules
is_primary_with_prime
— Methodis_primary_with_prime(T::TorQuadModule) -> Bool, ZZRingElem
Given a torsion quadratic module T
, return whether the underlying (finite) abelian group of T
(see abelian_group
) is a p
-group for some prime number p
. In case it is, p
is also returned as second output.
Note that in the case of trivial groups, this function returns (true, 1)
. If T
is not primary, the second return value is -1
by default.
is_primary
— Methodis_primary(T::TorQuadModule, p::Union{Integer, ZZRingElem}) -> Bool
Given a torsion quadratic module T
and a prime number p
, return whether the underlying (finite) abelian group of T
(see abelian_group
) is a p
-group.
is_elementary_with_prime
— Methodis_elementary_with_prime(T::TorQuadModule) -> Bool, ZZRingElem
Given a torsion quadratic module T
, return whether the underlying (finite) abelian group of T
(see abelian_group
) is an elementary p
-group, for some prime number p
. In case it is, p
is also returned as second output.
Note that in the case of trivial groups, this function returns (true, 1)
. If T
is not elementary, the second return value is -1
by default.
is_elementary
— Methodis_elementary(T::TorQuadModule, p::Union{Integer, ZZRingElem}) -> Bool
Given a torsion quadratic module T
and a prime number p
, return whether the underlying (finite) abelian group of T
(see abelian_group
) is an elementary p
-group.
Smith normal form
snf
— Methodsnf(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMor
Given a torsion quadratic module T
, return a torsion quadratic module S
, isometric to T
, such that the underlying abelian group of S
is in canonical Smith normal form. It comes with an isometry $f : S \to T$.
is_snf
— Methodis_snf(T::TorQuadModule) -> Bool
Given a torsion quadratic module T
, return whether its underlying abelian group is in Smith normal form.
Discriminant Groups
See V. V. Nikulin (1979) for the general theory of discriminant groups. They are particularly useful to work with primitive embeddings of integral integer quadratic lattices.
From a lattice
discriminant_group
— Methoddiscriminant_group(L::ZZLat) -> TorQuadModule
Return the discriminant group of L
.
The discriminant group of an integral lattice L
is the finite abelian group D = dual(L)/L
.
It comes equipped with the discriminant bilinear form
\[D \times D \to \mathbb{Q} / \mathbb{Z} \qquad (x,y) \mapsto \Phi(x,y) + \mathbb{Z}.\]
If L
is even, then the discriminant group is equipped with the discriminant quadratic form $D \to \mathbb{Q} / 2 \mathbb{Z}, x \mapsto \Phi(x,x) + 2\mathbb{Z}$.
From a matrix
torsion_quadratic_module
— Methodtorsion_quadratic_module(q::QQMatrix) -> TorQuadModule
Return a torsion quadratic module with gram matrix given by q
and value module Q/Z
. If all the diagonal entries of q
have: either even numerator or even denominator, then the value module of the quadratic form is Q/2Z
Example
julia> torsion_quadratic_module(QQ[1//6;])
Finite quadratic module
over integer ring
Abelian group: Z/6
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[1//6]
julia> torsion_quadratic_module(QQ[1//2;])
Finite quadratic module
over integer ring
Abelian group: Z/2
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[1//2]
julia> torsion_quadratic_module(QQ[3//2;])
Finite quadratic module
over integer ring
Abelian group: Z/2
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[3//2]
julia> torsion_quadratic_module(QQ[1//3;])
Finite quadratic module
over integer ring
Abelian group: Z/3
Bilinear value module: Q/Z
Quadratic value module: Q/Z
Gram matrix quadratic form:
[1//3]
Rescaling the form
rescale
— Methodrescale(T::TorQuadModule, k::RingElement) -> TorQuadModule
Return the torsion quadratic module with quadratic form scaled by $k$, where k is a non-zero rational number. If the old form was defined modulo n
, then the new form is defined modulo n k
.
Invariants
is_degenerate
— Methodis_degenerate(T::TorQuadModule) -> Bool
Return true if the underlying bilinear form is degenerate.
is_semi_regular
— Methodis_semi_regular(T::TorQuadModule) -> Bool
Return whether T
is semi-regular, that is its quadratic radical is trivial (see radical_quadratic
).
radical_bilinear
— Methodradical_bilinear(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMor
Return the radical \{x \in T | b(x,T) = 0\}
of the bilinear form b
on T
.
radical_quadratic
— Methodradical_quadratic(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMor
Return the radical \{x \in T | b(x,T) = 0 and q(x)=0\}
of the quadratic form q
on T
.
normal_form
— Methodnormal_form(T::TorQuadModule; partial=false) -> TorQuadModule, TorQuadModuleMor
Return the normal form N
of the given torsion quadratic module T
along with the projection T -> N
.
Let K
be the radical of the quadratic form of T
. Then N = T/K
is half-regular. Two half-regular torsion quadratic modules are isometric if and only if they have equal normal forms.
Genus
genus
— Methodgenus(T::TorQuadModule, signature_pair::Tuple{Int, Int}) -> ZZGenus
Return the genus of an integer lattice with discriminant group T
and the given signature_pair
. If no such genus exists, raise an error.
Reference
V. V. Nikulin (1979) Corollary 1.9.4 and 1.16.3.
brown_invariant
— Methodbrown_invariant(self::TorQuadModule) -> Nemo.zzModRingElem
Return the Brown invariant of this torsion quadratic form.
Let (D,q)
be a torsion quadratic module with values in Q / 2Z
. The Brown invariant Br(D,q) in Z/8Z
is defined by the equation
\[\exp \left( \frac{2 \pi i }{8} Br(q)\right) = \frac{1}{\sqrt{D}} \sum_{x \in D} \exp(i \pi q(x)).\]
The Brown invariant is additive with respect to direct sums of torsion quadratic modules.
Examples
julia> L = integer_lattice(gram=matrix(ZZ, [[2,-1,0,0],[-1,2,-1,-1],[0,-1,2,0],[0,-1,0,2]]));
julia> T = Hecke.discriminant_group(L);
julia> brown_invariant(T)
4
is_genus
— Methodis_genus(T::TorQuadModule, signature_pair::Tuple{Int, Int}) -> Bool
Return if there is an integral lattice with this signature and discriminant form.
Categorical constructions
direct_sum
— Methoddirect_sum(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}
direct_sum(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}
Given a collection of torsion quadratic modules $T_1, \ldots, T_n$, return their direct sum $T := T_1\oplus \ldots \oplus T_n$, together with the injections $T_i \to T$.
For objects of type TorQuadModule
, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain T
as a direct product with the projections $T \to T_i$, one should call direct_product(x)
. If one wants to obtain T
as a biproduct with the injections $T_i \to T$ and the projections $T \to T_i$, one should call biproduct(x)
.
direct_product
— Methoddirect_product(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}
direct_product(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}
Given a collection of torsion quadratic modules $T_1, \ldots, T_n$, return their direct product $T := T_1\times \ldots \times T_n$, together with the projections $T \to T_i$.
For objects of type TorQuadModule
, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain T
as a direct sum with the inctions $T_i \to T$, one should call direct_sum(x)
. If one wants to obtain T
as a biproduct with the injections $T_i \to T$ and the projections $T \to T_i$, one should call biproduct(x)
.
biproduct
— Methodbiproduct(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}, Vector{TorQuadModuleMor}
biproduct(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}, Vector{TorQuadModuleMor}
Given a collection of torsion quadratic modules $T_1, \ldots, T_n$, return their biproduct $T := T_1\oplus \ldots \oplus T_n$, together with the injections $T_i \to T$ and the projections $T \to T_i$.
For objects of type TorQuadModule
, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain T
as a direct sum with the inctions $T_i \to T$, one should call direct_sum(x)
. If one wants to obtain T
as a direct product with the projections $T \to T_i$, one should call direct_product(x)
.
Submodules
submodules
— Methodsubmodules(T::TorQuadMod; kw...)
Return the submodules of T
as an iterator. Possible keyword arguments to restrict the submodules:
order::Int
: only submodules of orderorder
,index::Int
: only submodules of indexindex
,subtype::Vector{Int}
: only submodules which are isomorphic as an abelian group toabelian_group(subtype)
,quotype::Vector{Int}
: only submodules whose quotient are isomorphic as an abelian toabelian_group(quotype)
.
stable_submodules
— Methodstable_submodules(T::TorQuadMod, act::Vector{TorQuadModuleMor}; kw...)
Return the submodules of T
stable under the endomorphisms in act
as an iterator. Possible keyword arguments to restrict the submodules:
quotype::Vector{Int}
: only submodules whose quotient are isomorphic as an abelian group toabelian_group(quotype)
.