Finite \(\ZZ\)-modules with bilinear and quadratic forms¶
AUTHORS:
- Simon Brandhorst (2017-09): First created 
- sage.modules.torsion_quadratic_module.TorsionQuadraticForm(q)[source]¶
- 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]) sage: TorsionQuadraticForm(q1) 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] - >>> from sage.all import * >>> q1 = Matrix(QQ, Integer(2), [Integer(1),Integer(1)/Integer(2),Integer(1)/Integer(2),Integer(1)]) >>> TorsionQuadraticForm(q1) 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]) sage: TorsionQuadraticForm(q2) Finite quadratic module over Integer Ring with invariants (12,) Gram matrix of the quadratic form with values in Q/Z: [7/12] - >>> from sage.all import * >>> q2 = diagonal_matrix(QQ, [Integer(1)/Integer(4),Integer(1)/Integer(3)]) >>> TorsionQuadraticForm(q2) Finite quadratic module over Integer Ring with invariants (12,) Gram matrix of the quadratic form with values in Q/Z: [7/12] 
- class sage.modules.torsion_quadratic_module.TorsionQuadraticModule(V, W, gens, modulus, modulus_qf)[source]¶
- Bases: - FGP_Module_class,- CachedRepresentation- Finite quotients with a bilinear and a quadratic form. - Let \(V\) be a symmetric - FreeQuadraticModuleand \(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- FreeModulewith a symmetric inner product matrix
- W– a submodule of- Vof the same rank as- V
- check– boolean (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: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = FreeModule(ZZ, 3) sage: T = TorsionQuadraticModule(V, 5*V); 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] - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = FreeModule(ZZ, Integer(3)) >>> T = TorsionQuadraticModule(V, Integer(5)*V); 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[source]¶
- alias of - TorsionQuadraticModuleElement
 - all_submodules()[source]¶
- 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() # needs sage.combinat sage: D.all_submodules() # needs sage.combinat [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]] - >>> from sage.all import * >>> D = IntegralLattice("D4").discriminant_group() # needs sage.combinat >>> D.all_submodules() # needs sage.combinat [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()[source]¶
- 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") # needs sage.combinat sage: D = L.discriminant_group() # needs sage.combinat sage: D.brown_invariant() # needs sage.combinat 4 - >>> from sage.all import * >>> L = IntegralLattice("D4") # needs sage.combinat >>> D = L.discriminant_group() # needs sage.combinat >>> D.brown_invariant() # needs sage.combinat 4 - We require the quadratic form to be defined modulo \(2 \ZZ\): - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)) sage: T = TorsionQuadraticModule((1/10)*V, V) sage: T.brown_invariant() Traceback (most recent call last): ... ValueError: the torsion quadratic form must have values in QQ / 2 ZZ - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = FreeQuadraticModule(ZZ, Integer(3), matrix.identity(Integer(3))) >>> T = TorsionQuadraticModule((Integer(1)/Integer(10))*V, V) >>> T.brown_invariant() Traceback (most recent call last): ... ValueError: the torsion quadratic form must have values in QQ / 2 ZZ 
 - gens()[source]¶
- Return generators of - self.- There is no assumption on the generators except that they generate the module. - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = FreeModule(ZZ, 3) sage: T = TorsionQuadraticModule(V, 5*V) sage: T.gens() ((1, 0, 0), (0, 1, 0), (0, 0, 1)) - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = FreeModule(ZZ, Integer(3)) >>> T = TorsionQuadraticModule(V, Integer(5)*V) >>> T.gens() ((1, 0, 0), (0, 1, 0), (0, 0, 1)) 
 - genus(signature_pair)[source]¶
- Return the genus defined by - selfand the- signature_pair.- If no such genus exists, raise a - ValueError.- REFERENCES: - [Nik1977] Corollary 1.9.4 and 1.16.3. - EXAMPLES: - sage: # needs sage.combinat sage: L = IntegralLattice("D4").direct_sum(IntegralLattice("A2")) sage: D = L.discriminant_group() sage: genus = D.genus(L.signature_pair()) # needs sage.libs.pari sage: genus # needs sage.libs.pari Genus of None Signature: (6, 0) Genus symbol at 2: 1^4:2^-2 Genus symbol at 3: 1^-5 3^-1 sage: genus == L.genus() # needs sage.libs.pari True - >>> from sage.all import * >>> # needs sage.combinat >>> L = IntegralLattice("D4").direct_sum(IntegralLattice("A2")) >>> D = L.discriminant_group() >>> genus = D.genus(L.signature_pair()) # needs sage.libs.pari >>> genus # needs sage.libs.pari Genus of None Signature: (6, 0) Genus symbol at 2: 1^4:2^-2 Genus symbol at 3: 1^-5 3^-1 >>> genus == L.genus() # needs sage.libs.pari True - Let \(H\) be an even unimodular lattice of signature \((9, 1)\). Then \(L = D_4 + A_2\) is primitively embedded in \(H\). We compute the discriminant form of the orthogonal complement of \(L\) in \(H\): - sage: DK = D.twist(-1) # needs sage.combinat sage.libs.pari sage: DK # needs sage.combinat sage.libs.pari 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] - >>> from sage.all import * >>> DK = D.twist(-Integer(1)) # needs sage.combinat sage.libs.pari >>> DK # needs sage.combinat sage.libs.pari 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] - We know that \(K\) has signature \((5, 1)\) and thus we can compute the genus of \(K\) as: - sage: DK.genus((3,1)) # needs sage.combinat sage.libs.pari Genus of None Signature: (3, 1) Genus symbol at 2: 1^2:2^-2 Genus symbol at 3: 1^-3 3^1 - >>> from sage.all import * >>> DK.genus((Integer(3),Integer(1))) # needs sage.combinat sage.libs.pari Genus of None Signature: (3, 1) Genus symbol at 2: 1^2:2^-2 Genus symbol at 3: 1^-3 3^1 - We can also compute the genus of an odd lattice from its discriminant form: - sage: L = IntegralLattice(matrix.diagonal(range(1, 5))) sage: D = L.discriminant_group() sage: D.genus((4,0)) # needs sage.libs.pari Genus of None Signature: (4, 0) Genus symbol at 2: [1^-2 2^1 4^1]_6 Genus symbol at 3: 1^-3 3^1 - >>> from sage.all import * >>> L = IntegralLattice(matrix.diagonal(range(Integer(1), Integer(5)))) >>> D = L.discriminant_group() >>> D.genus((Integer(4),Integer(0))) # needs sage.libs.pari Genus of None Signature: (4, 0) Genus symbol at 2: [1^-2 2^1 4^1]_6 Genus symbol at 3: 1^-3 3^1 
 - gram_matrix_bilinear()[source]¶
- Return the Gram matrix with respect to the generators. - OUTPUT: - A rational matrix - Gwith- 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: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)*5) sage: T = TorsionQuadraticModule((1/5)*V, V) sage: T.gram_matrix_bilinear() [1/5 0 0] [ 0 1/5 0] [ 0 0 1/5] - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = FreeQuadraticModule(ZZ, Integer(3), matrix.identity(Integer(3))*Integer(5)) >>> T = TorsionQuadraticModule((Integer(1)/Integer(5))*V, V) >>> T.gram_matrix_bilinear() [1/5 0 0] [ 0 1/5 0] [ 0 0 1/5] 
 - gram_matrix_quadratic()[source]¶
- The Gram matrix of the quadratic form with respect to the generators. - OUTPUT: - a rational matrix - Gqwith- Gq[i,j] = gens[i]*gens[j]and- G[i,i] = gens[i].q()
 - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule 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()) sage: discrForm = TorsionQuadraticModule(D4dual, D4) sage: discrForm.gram_matrix_quadratic() [ 1 1/2] [1/2 1] sage: discrForm.gram_matrix_bilinear() [ 0 1/2] [1/2 0] - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> D4_gram = Matrix(ZZ, [[Integer(2),Integer(0),Integer(0),-Integer(1)],[Integer(0),Integer(2),Integer(0),-Integer(1)],[Integer(0),Integer(0),Integer(2),-Integer(1)],[-Integer(1),-Integer(1),-Integer(1),Integer(2)]]) >>> D4 = FreeQuadraticModule(ZZ, Integer(4), D4_gram) >>> D4dual = D4.span(D4_gram.inverse()) >>> discrForm = TorsionQuadraticModule(D4dual, D4) >>> discrForm.gram_matrix_quadratic() [ 1 1/2] [1/2 1] >>> discrForm.gram_matrix_bilinear() [ 0 1/2] [1/2 0] 
 - is_genus(signature_pair, even=True)[source]¶
- Return - Trueif there is a lattice with this signature and discriminant form.- Todo - implement the same for odd lattices - INPUT: - signature_pair– tuple of nonnegative integers- (s_plus, s_minus)
- even– boolean (default:- True)
 - EXAMPLES: - sage: L3 = IntegralLattice(3 * Matrix(ZZ, 2, [2,1,1,2])) sage: L = IntegralLattice("D4").direct_sum(L3) # needs sage.combinat sage: D = L.discriminant_group() # needs sage.combinat sage: D.is_genus((6,0)) # needs sage.combinat True - >>> from sage.all import * >>> L3 = IntegralLattice(Integer(3) * Matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),Integer(2)])) >>> L = IntegralLattice("D4").direct_sum(L3) # needs sage.combinat >>> D = L.discriminant_group() # needs sage.combinat >>> D.is_genus((Integer(6),Integer(0))) # needs sage.combinat 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)) # needs sage.combinat False sage: D.is_genus((16,2)) # needs sage.combinat True - >>> from sage.all import * >>> D.is_genus((Integer(4),Integer(2))) # needs sage.combinat False >>> D.is_genus((Integer(16),Integer(2))) # needs sage.combinat True 
 - normal_form(partial=False)[source]¶
- 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 \times 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– boolean (default:- False); return only a partial normal form. It is not unique but still useful to extract invariants.
 - OUTPUT: a torsion quadratic module - EXAMPLES: - sage: L1 = IntegralLattice(matrix([[-2,0,0], [0,1,0], [0,0,4]])) sage: L1.discriminant_group().normal_form() # needs sage.rings.padics 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() # needs sage.rings.padics 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] - >>> from sage.all import * >>> L1 = IntegralLattice(matrix([[-Integer(2),Integer(0),Integer(0)], [Integer(0),Integer(1),Integer(0)], [Integer(0),Integer(0),Integer(4)]])) >>> L1.discriminant_group().normal_form() # needs sage.rings.padics 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] >>> L2 = IntegralLattice(matrix([[-Integer(2),Integer(0),Integer(0)], [Integer(0),Integer(1),Integer(0)], [Integer(0),Integer(0),-Integer(4)]])) >>> L2.discriminant_group().normal_form() # needs sage.rings.padics 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 Issue #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() # needs sage.rings.padics 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() # needs sage.libs.pari sage.rings.padics 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] - >>> from sage.all import * >>> L1 = IntegralLattice(matrix([[-Integer(4),Integer(0),Integer(0)], [Integer(0),Integer(4),Integer(0)], [Integer(0),Integer(0),-Integer(2)]])) >>> AL1 = L1.discriminant_group() >>> L2 = IntegralLattice(matrix([[-Integer(4),Integer(0),Integer(0)], [Integer(0),-Integer(4),Integer(0)], [Integer(0),Integer(0),Integer(2)]])) >>> AL2 = L2.discriminant_group() >>> AL1.normal_form() # needs sage.rings.padics 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] >>> AL2.normal_form() # needs sage.libs.pari sage.rings.padics 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: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: D4_gram = Matrix(ZZ, 4, 4,[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()) sage: T = TorsionQuadraticModule((1/6)*D4dual, D4); 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 1/12 5/36 1/36] [ 1/12 1/6 1/36 1/9] [ 5/36 1/36 1/36 11/72] [ 1/36 1/9 11/72 1/36] sage: T.normal_form() # needs sage.libs.pari sage.rings.padics 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] - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> D4_gram = Matrix(ZZ, Integer(4), Integer(4),[Integer(2),Integer(0),Integer(0),-Integer(1), Integer(0),Integer(2),Integer(0),-Integer(1), Integer(0),Integer(0),Integer(2),-Integer(1), -Integer(1),-Integer(1),-Integer(1),Integer(2)]) >>> D4 = FreeQuadraticModule(ZZ, Integer(4), D4_gram) >>> D4dual = D4.span(D4_gram.inverse()) >>> T = TorsionQuadraticModule((Integer(1)/Integer(6))*D4dual, D4); 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 1/12 5/36 1/36] [ 1/12 1/6 1/36 1/9] [ 5/36 1/36 1/36 11/72] [ 1/36 1/9 11/72 1/36] >>> T.normal_form() # needs sage.libs.pari sage.rings.padics 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_group(gens=None, check=False)[source]¶
- Orthogonal group of the associated torsion quadratic form. - Warning - This is can be smaller than the orthogonal group of the bilinear form. - INPUT: - gens– a list of generators, for instance square matrices, something that acts on- self, or an automorphism of the underlying abelian group
- check– perform additional checks on the generators
 - EXAMPLES: - You can provide generators to obtain a subgroup of the full orthogonal group: - sage: D = TorsionQuadraticForm(matrix.identity(2)/2) sage: f = matrix(2, [0,1,1,0]) sage: D.orthogonal_group(gens=[f]).order() # needs sage.groups 2 - >>> from sage.all import * >>> D = TorsionQuadraticForm(matrix.identity(Integer(2))/Integer(2)) >>> f = matrix(Integer(2), [Integer(0),Integer(1),Integer(1),Integer(0)]) >>> D.orthogonal_group(gens=[f]).order() # needs sage.groups 2 - If no generators are given a slow brute force approach is used to calculate the full orthogonal group: - sage: D = TorsionQuadraticForm(matrix.identity(3)/2) sage: OD = D.orthogonal_group() # needs sage.groups sage: OD.order() # needs sage.groups 6 sage: fd = D.hom([D.1, D.0, D.2]) # needs sage.symbolic sage: OD(fd) # needs sage.groups sage.symbolic [0 1 0] [1 0 0] [0 0 1] - >>> from sage.all import * >>> D = TorsionQuadraticForm(matrix.identity(Integer(3))/Integer(2)) >>> OD = D.orthogonal_group() # needs sage.groups >>> OD.order() # needs sage.groups 6 >>> fd = D.hom([D.gen(1), D.gen(0), D.gen(2)]) # needs sage.symbolic >>> OD(fd) # needs sage.groups sage.symbolic [0 1 0] [1 0 0] [0 0 1] - We compute the kernel of the action of the orthogonal group of \(L\) on the discriminant group: - sage: # needs sage.combinat sage.groups sage: L = IntegralLattice('A4') sage: O = L.orthogonal_group() sage: D = L.discriminant_group() sage: Obar = D.orthogonal_group(O.gens()) sage: O.order() 240 sage: Obar.order() 2 sage: phi = O.hom(Obar.gens()) sage: phi.kernel().order() 120 - >>> from sage.all import * >>> # needs sage.combinat sage.groups >>> L = IntegralLattice('A4') >>> O = L.orthogonal_group() >>> D = L.discriminant_group() >>> Obar = D.orthogonal_group(O.gens()) >>> O.order() 240 >>> Obar.order() 2 >>> phi = O.hom(Obar.gens()) >>> phi.kernel().order() 120 
 - orthogonal_submodule_to(S)[source]¶
- Return the submodule orthogonal to - S.- INPUT: - S– a submodule, list, or tuple of generators
 - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = FreeModule(ZZ, 10) sage: T = TorsionQuadraticModule(V, 3*V) 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 - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = FreeModule(ZZ, Integer(10)) >>> T = TorsionQuadraticModule(V, Integer(3)*V) >>> S = T.submodule(T.gens()[:Integer(5)]) >>> O = T.orthogonal_submodule_to(S) >>> 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] >>> O.V() + S.V() == T.V() True 
 - primary_part(m)[source]¶
- Return the - m-primary part of this torsion quadratic module as a submodule.- INPUT: - m– integer
 - OUTPUT: a submodule - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: T = TorsionQuadraticModule((1/6)*ZZ^3, ZZ^3); 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] - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> T = TorsionQuadraticModule((Integer(1)/Integer(6))*ZZ**Integer(3), ZZ**Integer(3)); 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] >>> T.primary_part(Integer(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)[source]¶
- Return a submodule with generators given by - gens.- INPUT: - gens– list of generators that convert into- self
 - OUTPUT: a submodule with the specified generators - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)*10) sage: T = TorsionQuadraticModule((1/10)*V, V) 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] - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = FreeQuadraticModule(ZZ, Integer(3), matrix.identity(Integer(3))*Integer(10)) >>> T = TorsionQuadraticModule((Integer(1)/Integer(10))*V, V) >>> g = T.gens() >>> new_gens = [Integer(2)*g[Integer(0)], Integer(5)*g[Integer(0)]] >>> 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] - >>> from sage.all import * >>> new_gens = [g[Integer(0)], Integer(2)*g[Integer(1)], g[Integer(0)], g[Integer(1)]] >>> 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)[source]¶
- Return the torsion quadratic module with quadratic form scaled by - 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 = TorsionQuadraticForm(matrix.diagonal([3/9, 1/9])) 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] - >>> from sage.all import * >>> q = TorsionQuadraticForm(matrix.diagonal([Integer(3)/Integer(9), Integer(1)/Integer(9)])) >>> q.twist(-Integer(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] - >>> from sage.all import * >>> q.twist(Integer(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] - >>> from sage.all import * >>> q.twist(Integer(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()[source]¶
- 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(); 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 - >>> from sage.all import * >>> A2 = Matrix(ZZ, Integer(2), Integer(2), [Integer(2),-Integer(1),-Integer(1),Integer(2)]) >>> L = IntegralLattice(Integer(2)*A2) >>> D = L.discriminant_group(); 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] >>> D.value_module() Q/Z 
 - value_module_qf()[source]¶
- 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(); 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 - >>> from sage.all import * >>> A2 = Matrix(ZZ, Integer(2), Integer(2), [Integer(2),-Integer(1),-Integer(1),Integer(2)]) >>> L = IntegralLattice(Integer(2) * A2) >>> D = L.discriminant_group(); 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] >>> D.value_module_qf() Q/2Z 
 
- class sage.modules.torsion_quadratic_module.TorsionQuadraticModuleElement(parent, x, check=True)[source]¶
- Bases: - FGP_Element- An element of a torsion quadratic module. - INPUT: - parent– parent
- x– element of- parent.V()
- check– boolean (default:- True)
 - b(other)[source]¶
- Compute the inner product of two elements. - OUTPUT: - an element of \(\QQ / m\ZZ\) with \(m\ZZ = (V, W)\) 
 - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = (1/2)*ZZ^2; W = ZZ^2 sage: T = TorsionQuadraticModule(V, W) sage: g = T.gens() sage: x = g[0]; x (1, 0) sage: y = g[0] + g[1] sage: x*y 1/4 - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = (Integer(1)/Integer(2))*ZZ**Integer(2); W = ZZ**Integer(2) >>> T = TorsionQuadraticModule(V, W) >>> g = T.gens() >>> x = g[Integer(0)]; x (1, 0) >>> y = g[Integer(0)] + g[Integer(1)] >>> x*y 1/4 - The inner product has further aliases: - sage: x.inner_product(y) 1/4 sage: x.b(y) 1/4 - >>> from sage.all import * >>> x.inner_product(y) 1/4 >>> x.b(y) 1/4 
 - inner_product(other)[source]¶
- Compute the inner product of two elements. - OUTPUT: - an element of \(\QQ / m\ZZ\) with \(m\ZZ = (V, W)\) 
 - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: V = (1/2)*ZZ^2; W = ZZ^2 sage: T = TorsionQuadraticModule(V, W) sage: g = T.gens() sage: x = g[0]; x (1, 0) sage: y = g[0] + g[1] sage: x*y 1/4 - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> V = (Integer(1)/Integer(2))*ZZ**Integer(2); W = ZZ**Integer(2) >>> T = TorsionQuadraticModule(V, W) >>> g = T.gens() >>> x = g[Integer(0)]; x (1, 0) >>> y = g[Integer(0)] + g[Integer(1)] >>> x*y 1/4 - The inner product has further aliases: - sage: x.inner_product(y) 1/4 sage: x.b(y) 1/4 - >>> from sage.all import * >>> x.inner_product(y) 1/4 >>> x.b(y) 1/4 
 - q()[source]¶
- Compute the quadratic product of - self.- OUTPUT: - an element of \(\QQ / n\ZZ\) where \(n\ZZ = 2(V,W) + \ZZ \{ (w,w) | w \in W \}\) 
 - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: W = FreeQuadraticModule(ZZ, 2, 2*matrix.identity(2)) sage: V = (1/2) * W sage: T = TorsionQuadraticModule(V, W) sage: x = T.gen(0) sage: x (1, 0) sage: x.quadratic_product() 1/2 sage: x.quadratic_product().parent() Q/2Z sage: x*x 1/2 sage: (x*x).parent() Q/Z - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> W = FreeQuadraticModule(ZZ, Integer(2), Integer(2)*matrix.identity(Integer(2))) >>> V = (Integer(1)/Integer(2)) * W >>> T = TorsionQuadraticModule(V, W) >>> x = T.gen(Integer(0)) >>> x (1, 0) >>> x.quadratic_product() 1/2 >>> x.quadratic_product().parent() Q/2Z >>> x*x 1/2 >>> (x*x).parent() Q/Z 
 - quadratic_product()[source]¶
- Compute the quadratic product of - self.- OUTPUT: - an element of \(\QQ / n\ZZ\) where \(n\ZZ = 2(V,W) + \ZZ \{ (w,w) | w \in W \}\) 
 - EXAMPLES: - sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule sage: W = FreeQuadraticModule(ZZ, 2, 2*matrix.identity(2)) sage: V = (1/2) * W sage: T = TorsionQuadraticModule(V, W) sage: x = T.gen(0) sage: x (1, 0) sage: x.quadratic_product() 1/2 sage: x.quadratic_product().parent() Q/2Z sage: x*x 1/2 sage: (x*x).parent() Q/Z - >>> from sage.all import * >>> from sage.modules.torsion_quadratic_module import TorsionQuadraticModule >>> W = FreeQuadraticModule(ZZ, Integer(2), Integer(2)*matrix.identity(Integer(2))) >>> V = (Integer(1)/Integer(2)) * W >>> T = TorsionQuadraticModule(V, W) >>> x = T.gen(Integer(0)) >>> x (1, 0) >>> x.quadratic_product() 1/2 >>> x.quadratic_product().parent() Q/2Z >>> x*x 1/2 >>> (x*x).parent() Q/Z