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::RationalUnion = QQFieldElem(0),
modulus_qf::RationalUnion = 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.
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
— 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)
(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(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
— Methodabelian_group(T::TorQuadModule) -> FinGenAbGroup
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, TorQuadModuleMap
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: 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)
true
is_anti_isometric_with_anti_isometry
— Methodis_anti_isometric_with_anti_isometry(T::TorQuadModule, U::TorQuadModule)
-> Bool, TorQuadModuleMap
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: 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)
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, TorQuadModuleMap
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 [Nik79] 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, TorQuadModuleMap
Return the radical \{x \in T | b(x,T) = 0\}
of the bilinear form b
on T
.
radical_quadratic
— Methodradical_quadratic(T::TorQuadModule) -> TorQuadModule, TorQuadModuleMap
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, TorQuadModuleMap
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};
parity::RationalUnion = modulus_quadratic_form(T))
-> ZZGenus
Return 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
[Nik79] 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};
parity::RationalUnion = modulus_quadratic_form(T)) -> Bool
Return 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
— Methoddirect_sum(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}
direct_sum(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}
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{TorQuadModuleMap}
direct_product(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}
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{TorQuadModuleMap}, Vector{TorQuadModuleMap}
biproduct(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMap}, Vector{TorQuadModuleMap}
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::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
— Methodstable_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)
.