Discriminant Groups
Torsion Quadratic Modules
A torsion quadratic module is the quotient
as well as a quadratic form
where
torsion_quadratic_module Method
torsion_quadratic_module(M::ZZLat, N::ZZLat; gens::Union{Nothing, Vector{<:Vector}} = nothing,
snf::Bool = true,
modulus::RationalUnion = QQFieldElem(0),
modulus_qf::RationalUnion = QQFieldElem(0),
check::Bool = true) -> TorQuadModuleGiven a Z-lattice
If gens is set, the images of gens will be used as the generators of the abelian group
If snf is true, the underlying abelian group will be in Smith normal form. Otherwise, the images of the basis of
One can decide on the modulus for the associated finite bilinear and quadratic forms by setting modulus and modulus_qf respectively to the desired values.
The underlying Type
TorQuadModule Type
TorQuadModuleExamples
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
We store them as a 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 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)
(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
1N.B. Since there are no 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(basis_matrix(M), v; side = :left).
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 Method
abelian_group(T::TorQuadModule) -> FinGenAbGroupReturn the underlying abelian group of T.
value_module Method
value_module(T::TorQuadModule) -> QmodnZReturn the value module Q/nZ of the bilinear form of T.
value_module_quadratic_form Method
value_module_quadratic_form(T::TorQuadModule) -> QmodnZReturn the value module Q/mZ of the quadratic form of T.
gram_matrix_bilinear Method
gram_matrix_bilinear(T::TorQuadModule) -> QQMatrixReturn the gram matrix of the bilinear form of T.
gram_matrix_quadratic Method
gram_matrix_quadratic(T::TorQuadModule) -> QQMatrixReturn 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.
sourcemodulus_bilinear_form Method
modulus_bilinear_form(T::TorQuadModule) -> QQFieldElemReturn the modulus of the value module of the bilinear form ofT.
modulus_quadratic_form Method
modulus_quadratic_form(T::TorQuadModule) -> QQFieldElemReturn the modulus of the value module of the quadratic form of T.
Elements
quadratic_product Method
quadratic_product(a::TorQuadModuleElem) -> QmodnZElemReturn the quadratic product of a.
It is defined in terms of a representative: for
inner_product Method
inner_product(a::TorQuadModuleElem, b::TorQuadModuleElem) -> QmodnZElemReturn the inner product of a and b.
Lift to the cover
lift Method
lift(a::TorQuadModuleElem) -> Vector{QQFieldElem}Lift a to the ambient space of cover(parent(a)).
For
representative Method
representative(a::TorQuadModuleElem) -> Vector{QQFieldElem}For lift(a).
Orthogonal submodules
orthogonal_submodule Method
orthogonal_submodule(T::TorQuadModule, S::TorQuadModule)-> TorQuadModuleReturn the orthogonal submodule to the submodule S of T.
Isometry
is_isometric_with_isometry Method
is_isometric_with_isometry(T::TorQuadModule, U::TorQuadModule)
-> Bool, TorQuadModuleMapReturn whether the torsion quadratic modules T and U are isometric. If yes, it also returns an isometry
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: finite quadratic module -> finite quadratic module)
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: finite quadratic module -> finite quadratic module)
julia> U2, _ = sub(T, [T[4], T[2]+T[3]+T[5]])
(Finite quadratic module: (Z/3)^2 -> Q/2Z, Map: finite quadratic module -> finite quadratic module)
julia> bool, phi = is_isometric_with_isometry(U2, T2)
(true, Map: finite quadratic module -> finite quadratic module)
julia> is_bijective(phi)
trueis_anti_isometric_with_anti_isometry Method
is_anti_isometric_with_anti_isometry(T::TorQuadModule, U::TorQuadModule)
-> Bool, TorQuadModuleMapReturn whether there exists an anti-isometry between the torsion quadratic modules T and U. If yes, it returns such an anti-isometry
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: finite quadratic module -> finite quadratic module)
julia> a = gens(T)[1];
julia> a*a == -phi(a)*phi(a)
true
julia> G = matrix(QQ, 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(QQ, 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: finite quadratic module -> finite quadratic module)
julia> a = gens(T)[1];
julia> a*a == -phi(a)*phi(a)
truePrimary and elementary modules
is_primary_with_prime Method
is_primary_with_prime(T::TorQuadModule) -> Bool, ZZRingElemGiven 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 Method
is_primary(T::TorQuadModule, p::Union{Integer, ZZRingElem}) -> BoolGiven 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 Method
is_elementary_with_prime(T::TorQuadModule) -> Bool, ZZRingElemGiven 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 Method
is_elementary(T::TorQuadModule, p::Union{Integer, ZZRingElem}) -> BoolGiven 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 Method
snf(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMapGiven 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
is_snf Method
is_snf(T::TorQuadModule) -> BoolGiven a torsion quadratic module T, return whether its underlying abelian group is in Smith normal form.
Discriminant Groups
See [6] 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 Method
discriminant_group(L::ZZLat, [n::Int]) -> TorQuadModuleReturn 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
If L is even, then the discriminant group is equipped with the discriminant quadratic form
Input:
n::Int– if given, return the-primary part of the discriminant group
Examples:
julia> L = rescale(root_lattice(:A,2),10)
Integer lattice of rank 2 and degree 2
with gram matrix
[ 20 -10]
[-10 20]
julia> discriminant_group(L)
Finite quadratic module
over integer ring
Abelian group: Z/10 x Z/30
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[ 1//5 1//10]
[1//10 1//15]
julia> discriminant_group(L, 10)
Finite quadratic module
over integer ring
Abelian group: (Z/10)^2
Bilinear value module: Q/Z
Quadratic value module: Q/2Z
Gram matrix quadratic form:
[ 1 1//2 0 0]
[1//2 1 0 0]
[ 0 0 4//5 1//5]
[ 0 0 1//5 2//5]From a matrix
torsion_quadratic_module Method
torsion_quadratic_module(q::QQMatrix) -> TorQuadModuleReturn 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 Method
rescale(T::TorQuadModule, k::RingElement) -> TorQuadModuleReturn the torsion quadratic module with quadratic form scaled by n, then the new form is defined modulo n k.
Invariants
is_degenerate Method
is_degenerate(T::TorQuadModule) -> BoolReturn true if the underlying bilinear form is degenerate.
sourceis_semi_regular Method
is_semi_regular(T::TorQuadModule) -> BoolReturn whether T is semi-regular, that is its quadratic radical is trivial (see radical_quadratic).
radical_bilinear Method
radical_bilinear(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMapReturn the radical \{x \in T | b(x,T) = 0\} of the bilinear form b on T.
radical_quadratic Method
radical_quadratic(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMapReturn the radical \{x \in T | b(x,T) = 0 and q(x)=0\} of the quadratic form q on T.
normal_form Method
normal_form(T::TorQuadModule; partial=false) -> TorQuadModule, TorQuadModuleMapReturn 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 Method
genus(T::TorQuadModule, signature_pair::Tuple{Int, Int};
parity::RationalUnion = modulus_quadratic_form(T))
-> ZZGenusReturn the genus of an integer lattice whose discriminant group has the bilinear form of T, the given signature_pair and the given parity.
The argument parity is one of the following: either parity == 1 for genera of odd lattices, or parity == 2 for even lattices. By default, parity is set to be as the parity of the quadratic form on T
If no such genus exists, raise an error.
Reference
[6] Corollary 1.9.4 and 1.16.3.
sourcebrown_invariant Method
brown_invariant(self::TorQuadModule) -> Nemo.zzModRingElemReturn 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
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)
4is_genus Method
is_genus(T::TorQuadModule, signature_pair::Tuple{Int, Int};
parity::RationalUnion = modulus_quadratic_form(T)) -> BoolReturn if there is an integral lattice whose discriminant form has the bilinear form of T, whose signatures match signature_pair and which is of parity parity.
The argument parity is one of the following: either parity == 1 for genera of odd lattices, or parity == 2 for even lattices. By default, parity is set to be as the parity of the quadratic form on T
Categorical constructions
direct_sum Method
direct_sum(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}
direct_sum(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}Given a collection of torsion quadratic modules
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 direct_product(x). If one wants to obtain T as a biproduct with the injections biproduct(x).
direct_product Method
direct_product(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}
direct_product(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}Given a collection of torsion quadratic modules
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 direct_sum(x). If one wants to obtain T as a biproduct with the injections biproduct(x).
biproduct Method
biproduct(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}, Vector{TorQuadModuleMap}
biproduct(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}, Vector{TorQuadModuleMap}Given a collection of torsion quadratic modules
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 direct_sum(x). If one wants to obtain T as a direct product with the projections direct_product(x).
Submodules
submodules Method
submodules(T::TorQuadModule; 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 Method
stable_submodules(T::TorQuadModule, act::Vector{TorQuadModuleMap}; 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).
