# Finite $$\ZZ$$-modules with with bilinear and quadratic forms.¶

AUTHORS:

• Simon Brandhorst (2017-09): First created

Create a torsion quadratic form module from a rational matrix.

The resulting quadratic form takes values in $$\QQ / \ZZ$$ or $$\QQ / 2 \ZZ$$ (depending on q). If it takes values modulo $$2$$, then it is non-degenerate. In any case the bilinear form is non-degenerate.

INPUT:

• q – a symmetric rational matrix

EXAMPLES:

sage: q1 = Matrix(QQ,2,[1,1/2,1/2,1])
Finite quadratic module over Integer Ring with invariants (2, 2)
Gram matrix of the quadratic form with values in Q/2Z:
[  1 1/2]
[1/2   1]

In the following example the quadratic form is degenerate. But the bilinear form is still non-degenerate:

sage: q2 = diagonal_matrix(QQ,[1/4,1/3])
Finite quadratic module over Integer Ring with invariants (12,)
Gram matrix of the quadratic form with values in Q/Z:
[7/12]

Finite quotients with a bilinear and a quadratic form.

Let $$V$$ be a symmetric FreeQuadraticModule and $$W \subseteq V$$ a submodule of the same rank as $$V$$. The quotient $$V / W$$ is a torsion quadratic module. It inherits a bilinear form $$b$$ and a quadratic form $$q$$.

$$b: V \times V \to \QQ / m\ZZ$$, where $$m\ZZ = (V,W)$$ and $$b(x,y) = (x,y) + m\ZZ$$

$$q: V \to \QQ / n\ZZ$$, where $$n\ZZ = 2(V,W) + \ZZ \{ (w,w) | w \in W \}$$

INPUT:

• V – a FreeModule with a symmetric inner product matrix
• W – a submodule of V of the same rank as V
• check – bool (default: True)
• modulus – a rational number dividing $$m$$ (default: $$m$$); the inner product $$b$$ is defined in $$\QQ /$$ modulus $$\ZZ$$
• modulus_qf – a rational number dividing $$n$$ (default: $$n$$); the quadratic form $$q$$ is defined in $$\QQ /$$ modulus_qf $$\ZZ$$

EXAMPLES:

sage: V = FreeModule(ZZ, 3)
sage: T
Finite quadratic module over Integer Ring with invariants (5, 5, 5)
Gram matrix of the quadratic form with values in Q/5Z:
[1 0 0]
[0 1 0]
[0 0 1]
Element

all_submodules()

Return a list of all submodules of self.

WARNING:

This method creates all submodules in memory. The number of submodules grows rapidly with the number of generators. For example consider a vector space of dimension $$n$$ over a finite field of prime order $$p$$. The number of subspaces is (very) roughly $$p^{(n^2-n)/2}$$.

EXAMPLES:

sage: D = IntegralLattice("D4").discriminant_group()
sage: D.all_submodules()
[Finite quadratic module over Integer Ring with invariants ()
Gram matrix of the quadratic form with values in Q/2Z:
[],
Finite quadratic module over Integer Ring with invariants (2,)
Gram matrix of the quadratic form with values in Q/2Z:
[1],
Finite quadratic module over Integer Ring with invariants (2,)
Gram matrix of the quadratic form with values in Q/2Z:
[1],
Finite quadratic module over Integer Ring with invariants (2,)
Gram matrix of the quadratic form with values in Q/2Z:
[1],
Finite quadratic module over Integer Ring with invariants (2, 2)
Gram matrix of the quadratic form with values in Q/2Z:
[  1 1/2]
[1/2   1]]
brown_invariant()

Return the Brown invariant of this torsion quadratic form.

Let $$(D,q)$$ be a torsion quadratic module with values in $$\QQ / 2 \ZZ$$. The Brown invariant $$Br(D,q) \in \Zmod{8}$$ 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.

OUTPUT:

• an element of $$\Zmod{8}$$

EXAMPLES:

sage: L = IntegralLattice("D4")
sage: D = L.discriminant_group()
sage: D.brown_invariant()
4

We require the quadratic form to be defined modulo $$2 \ZZ$$:

sage: T.brown_invariant()
Traceback (most recent call last):
...
ValueError: the torsion quadratic form must have values in QQ / 2 ZZ
gens()

Return generators of self.

There is no assumption on the generators except that they generate the module.

EXAMPLES:

sage: V = FreeModule(ZZ, 3)
sage: T.gens()
((1, 0, 0), (0, 1, 0), (0, 0, 1))
gram_matrix_bilinear()

Return the gram matrix with respect to the generators.

OUTPUT:

A rational matrix G with G[i,j] given by the inner product of the $$i$$-th and $$j$$-th generator. Its entries are only well defined $$\mod (V, W)$$.

EXAMPLES:

sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)*5)
sage: T.gram_matrix_bilinear()
[1/5   0   0]
[  0 1/5   0]
[  0   0 1/5]

The gram matrix of the quadratic form with respect to the generators.

OUTPUT:

• a rational matrix Gq with Gq[i,j] = gens[i]*gens[j] and G[i,i] = gens[i].q()

EXAMPLES:

sage: D4_gram = Matrix(ZZ, [[2,0,0,-1],[0,2,0,-1],[0,0,2,-1],[-1,-1,-1,2]])
sage: D4 = FreeQuadraticModule(ZZ, 4, D4_gram)
sage: D4dual = D4.span(D4_gram.inverse())
[  1 1/2]
[1/2   1]
sage: discrForm.gram_matrix_bilinear()
[  0 1/2]
[1/2   0]
is_genus(signature_pair, even=True)

Return True if there is a lattice with this signature and discriminant form.

TODO:

• implement the same for odd lattices

INPUT:

• signature_pair – a tuple of non negative integers (s_plus, s_minus)
• even – bool (default: True)

EXAMPLES:

sage: L = IntegralLattice("D4").direct_sum(IntegralLattice(3 * Matrix(ZZ,2,[2,1,1,2])))
sage: D = L.discriminant_group()
sage: D.is_genus((6,0))
True

Let us see if there is a lattice in the genus defined by the same discriminant form but with a different signature:

sage: D.is_genus((4,2))
False
sage: D.is_genus((16,2))
True
normal_form(partial=False)

Return the normal form of this torsion quadratic module.

Two torsion quadratic modules are isomorphic if and only if they have the same value modules and the same normal form.

A torsion quadratic module $$(T,q)$$ with values in $$\QQ/n\ZZ$$ is in normal form if the rescaled quadratic module $$(T, q/n)$$ with values in $$\QQ/\ZZ$$ is in normal form.

For the definition of normal form see [MirMor2009] IV Definition 4.6. Below are some of its properties. Let $$p$$ be odd and $$u$$ be the smallest non-square modulo $$p$$. The normal form is a diagonal matrix with diagonal entries either $$p^n$$ or $$u p^n$$.

If $$p = 2$$ is even, then the normal form consists of 1 x 1 blocks of the form

$(0), \quad 2^n(1),\quad 2^n(3),\quad 2^n(5) ,\quad 2^n(7)$

or of $$2 \times 2$$ blocks of the form

$\begin{split}2^n \left(\begin{matrix} 2 & 1\\ 1 & 2 \end{matrix}\right), \quad 2^n \left(\begin{matrix} 0 & 1\\ 1 & 0 \end{matrix}\right).\end{split}$

The blocks are ordered by their valuation.

INPUT:

• partial - bool (default: False) return only a partial normal form it is not unique but still useful to extract invariants

OUTPUT:

EXAMPLES:

sage: L1=IntegralLattice(matrix([[-2,0,0],[0,1,0],[0,0,4]]))
sage: L1.discriminant_group().normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4)
Gram matrix of the quadratic form with values in Q/Z:
[1/2   0]
[  0 1/4]
sage: L2=IntegralLattice(matrix([[-2,0,0],[0,1,0],[0,0,-4]]))
sage: L2.discriminant_group().normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4)
Gram matrix of the quadratic form with values in Q/Z:
[1/2   0]
[  0 1/4]

We check that trac ticket #24864 is fixed:

sage: L1=IntegralLattice(matrix([[-4,0,0],[0,4,0],[0,0,-2]]))
sage: AL1=L1.discriminant_group()
sage: L2=IntegralLattice(matrix([[-4,0,0],[0,-4,0],[0,0,2]]))
sage: AL2=L2.discriminant_group()
sage: AL1.normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4, 4)
Gram matrix of the quadratic form with values in Q/2Z:
[1/2   0   0]
[  0 1/4   0]
[  0   0 5/4]
sage: AL2.normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4, 4)
Gram matrix of the quadratic form with values in Q/2Z:
[1/2   0   0]
[  0 1/4   0]
[  0   0 5/4]

Some exotic cases:

sage: D4_gram = Matrix(ZZ,4,4,[2,0,0,-1,0,2,0,-1,0,0,2,-1,-1,-1,-1,2])
sage: D4dual = D4.span(D4_gram.inverse())
sage: T
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
Gram matrix of the quadratic form with values in Q/(1/3)Z:
[1/18 5/36    0    0]
[5/36 1/18 5/36 5/36]
[   0 5/36 1/36 1/72]
[   0 5/36 1/72 1/36]
sage: T.normal_form()
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
Gram matrix of the quadratic form with values in Q/(1/3)Z:
[ 1/6 1/12    0    0    0    0    0    0]
[1/12  1/6    0    0    0    0    0    0]
[   0    0 1/12 1/24    0    0    0    0]
[   0    0 1/24 1/12    0    0    0    0]
[   0    0    0    0  1/9    0    0    0]
[   0    0    0    0    0  1/9    0    0]
[   0    0    0    0    0    0  1/9    0]
[   0    0    0    0    0    0    0  1/9]
orthogonal_submodule_to(S)

Return the submodule orthogonal to S.

INPUT:

• S – a submodule, list, or tuple of generators

EXAMPLES:

sage: V = FreeModule(ZZ, 10)
sage: S = T.submodule(T.gens()[:5])
sage: O = T.orthogonal_submodule_to(S)
sage: O
Finite quadratic module over Integer Ring with invariants (3, 3, 3, 3, 3)
Gram matrix of the quadratic form with values in Q/3Z:
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]
sage: O.V() + S.V() == T.V()
True
primary_part(m)

Return the m-primary part of this torsion quadratic module as a submodule.

INPUT:

• m – an integer

OUTPUT:

• a submodule

EXAMPLES:

sage: T
Finite quadratic module over Integer Ring with invariants (6, 6, 6)
Gram matrix of the quadratic form with values in Q/(1/3)Z:
[1/36    0    0]
[   0 1/36    0]
[   0    0 1/36]
sage: T.primary_part(2)
Finite quadratic module over Integer Ring with invariants (2, 2, 2)
Gram matrix of the quadratic form with values in Q/(1/3)Z:
[1/4   0   0]
[  0 1/4   0]
[  0   0 1/4]
submodule_with_gens(gens)

Return a submodule with generators given by gens.

INPUT:

• gens – a list of generators that convert into self

OUTPUT:

• a submodule with the specified generators

EXAMPLES:

sage: g = T.gens()
sage: new_gens = [2*g[0], 5*g[0]]
sage: T.submodule_with_gens(new_gens)
Finite quadratic module over Integer Ring with invariants (10,)
Gram matrix of the quadratic form with values in Q/2Z:
[2/5   0]
[  0 1/2]

The generators do not need to be independent:

sage: new_gens = [g[0], 2*g[1], g[0], g[1]]
sage: T.submodule_with_gens(new_gens)
Finite quadratic module over Integer Ring with invariants (10, 10)
Gram matrix of the quadratic form with values in Q/2Z:
[1/10    0 1/10    0]
[   0  2/5    0  1/5]
[1/10    0 1/10    0]
[   0  1/5    0 1/10]
twist(s)

If the old form was defined modulo $$n$$, then the new form is defined modulo $$n s$$.

INPUT:

• s - a rational number

EXAMPLES:

sage: q.twist(-1)
Finite quadratic module over Integer Ring with invariants (3, 9)
Gram matrix of the quadratic form with values in Q/Z:
[2/3   0]
[  0 8/9]

This form is defined modulo $$3$$:

sage: q.twist(3)
Finite quadratic module over Integer Ring with invariants (3, 9)
Gram matrix of the quadratic form with values in Q/3Z:
[  1   0]
[  0 1/3]

The next form is defined modulo $$4$$:

sage: q.twist(4)
Finite quadratic module over Integer Ring with invariants (3, 9)
Gram matrix of the quadratic form with values in Q/4Z:
[4/3   0]
[  0 4/9]
value_module()

Return $$\QQ / m\ZZ$$ with $$m = (V, W)$$.

This is where the inner product takes values.

EXAMPLES:

sage: A2 = Matrix(ZZ, 2, 2, [2,-1,-1,2])
sage: L = IntegralLattice(2*A2)
sage: D = L.discriminant_group()
sage: D
Finite quadratic module over Integer Ring with invariants (2, 6)
Gram matrix of the quadratic form with values in Q/2Z:
[  1 1/2]
[1/2 1/3]
sage: D.value_module()
Q/Z
value_module_qf()

Return $$\QQ / n\ZZ$$ with $$n\ZZ = (V,W) + \ZZ \{ (w,w) | w \in W \}$$.

This is where the torsion quadratic form takes values.

EXAMPLES:

sage: A2 = Matrix(ZZ, 2, 2, [2,-1,-1,2])
sage: L = IntegralLattice(2*A2)
sage: D = L.discriminant_group()
sage: D
Finite quadratic module over Integer Ring with invariants (2, 6)
Gram matrix of the quadratic form with values in Q/2Z:
[  1 1/2]
[1/2 1/3]
sage: D.value_module_qf()
Q/2Z

An element of a torsion quadratic module.

INPUT:

• parent – parent
• x – element of parent.V()
• check – bool (default: True)
b(other)

Compute the inner product of two elements.

OUTPUT:

• an element of $$\QQ / m\ZZ$$ with $$m\ZZ = (V, W)$$

EXAMPLES:

sage: V = (1/2)*ZZ^2; W = ZZ^2
sage: g = T.gens()
sage: x = g[0]
sage: y = g[0] + g[1]
sage: x
(1, 0)
sage: x*y
1/4

The inner product has further aliases:

sage: x.inner_product(y)
1/4
sage: x.b(y)
1/4
inner_product(other)

Compute the inner product of two elements.

OUTPUT:

• an element of $$\QQ / m\ZZ$$ with $$m\ZZ = (V, W)$$

EXAMPLES:

sage: V = (1/2)*ZZ^2; W = ZZ^2
sage: g = T.gens()
sage: x = g[0]
sage: y = g[0] + g[1]
sage: x
(1, 0)
sage: x*y
1/4

The inner product has further aliases:

sage: x.inner_product(y)
1/4
sage: x.b(y)
1/4
q()

OUTPUT:

• an element of $$\QQ / n\ZZ$$ where $$n\ZZ = 2(V,W) + \ZZ \{ (w,w) | w \in W \}$$

EXAMPLES:

sage: W = FreeQuadraticModule(ZZ, 2, 2*matrix.identity(2))
sage: V = (1/2) * W
sage: x = T.gen(0)
sage: x
(1, 0)
1/2
Q/2Z
sage: x*x
1/2
sage: (x*x).parent()
Q/Z

OUTPUT:

• an element of $$\QQ / n\ZZ$$ where $$n\ZZ = 2(V,W) + \ZZ \{ (w,w) | w \in W \}$$

EXAMPLES:

sage: W = FreeQuadraticModule(ZZ, 2, 2*matrix.identity(2))
sage: V = (1/2) * W