Integral lattices¶
An integral lattice is a finitely generated free abelian group \(L \cong \ZZ^r\) equipped with a non-degenerate, symmetric bilinear form \(L \times L \colon \rightarrow \ZZ\).
Here, lattices have an ambient quadratic space \(\QQ^n\) and a distinguished basis.
EXAMPLES:
sage: M = Matrix(ZZ, [[0,1], [1,0]])
sage: IntegralLattice(M)
Lattice of degree 2 and rank 2 over Integer Ring
Standard basis
Inner product matrix:
[0 1]
[1 0]
>>> from sage.all import *
>>> M = Matrix(ZZ, [[Integer(0),Integer(1)], [Integer(1),Integer(0)]])
>>> IntegralLattice(M)
Lattice of degree 2 and rank 2 over Integer Ring
Standard basis
Inner product matrix:
[0 1]
[1 0]
A lattice can be defined by an inner product matrix of the ambient space and a basis:
sage: G = matrix.identity(3)
sage: basis = [[1,-1,0], [0,1,-1]]
sage: L = IntegralLattice(G, basis)
sage: L
Lattice of degree 3 and rank 2 over Integer Ring
Basis matrix:
[ 1 -1  0]
[ 0  1 -1]
Standard scalar product
sage: L.gram_matrix()
[ 2 -1]
[-1  2]
>>> from sage.all import *
>>> G = matrix.identity(Integer(3))
>>> basis = [[Integer(1),-Integer(1),Integer(0)], [Integer(0),Integer(1),-Integer(1)]]
>>> L = IntegralLattice(G, basis)
>>> L
Lattice of degree 3 and rank 2 over Integer Ring
Basis matrix:
[ 1 -1  0]
[ 0  1 -1]
Standard scalar product
>>> L.gram_matrix()
[ 2 -1]
[-1  2]
AUTHORS:
- Simon Brandhorst (2017-09): First created 
- Paolo Menegatti (2018-03): Added IntegralLatticeDirectSum, IntegralLatticeGluing 
- Lorenz Panny (2024): enumeration routines for short and close vectors 
- class sage.modules.free_quadratic_module_integer_symmetric.FreeQuadraticModule_integer_symmetric(ambient, basis, inner_product_matrix, check=True, already_echelonized=False)[source]¶
- Bases: - FreeQuadraticModule_submodule_with_basis_pid- This class represents non-degenerate, integral, symmetric free quadratic \(\ZZ\)-modules. - INPUT: - ambient– an ambient free quadratic module
- basis– list of elements of ambient or a matrix
- inner_product_matrix– a symmetric matrix over the rationals
 - EXAMPLES: - sage: IntegralLattice("U", basis=[vector([1,1])]) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [0 1] [1 0] - >>> from sage.all import * >>> IntegralLattice("U", basis=[vector([Integer(1),Integer(1)])]) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [0 1] [1 0] - LLL()[source]¶
- Return this lattice with an LLL reduced basis. - EXAMPLES: - sage: L = IntegralLattice('A2') # needs sage.graphs sage: L.lll() == L # needs sage.graphs sage.libs.pari True sage: G = matrix(ZZ, 3, [0,1,0, 1,0,0, 0,0,7]) sage: V = matrix(ZZ, 3, [-14,-15,-15, -4,1,16, -5,-5,-4]) sage: L = IntegralLattice(V * G * V.T) sage: L.lll().gram_matrix() # needs sage.libs.gap [0 0 1] [0 7 0] [1 0 0] - >>> from sage.all import * >>> L = IntegralLattice('A2') # needs sage.graphs >>> L.lll() == L # needs sage.graphs sage.libs.pari True >>> G = matrix(ZZ, Integer(3), [Integer(0),Integer(1),Integer(0), Integer(1),Integer(0),Integer(0), Integer(0),Integer(0),Integer(7)]) >>> V = matrix(ZZ, Integer(3), [-Integer(14),-Integer(15),-Integer(15), -Integer(4),Integer(1),Integer(16), -Integer(5),-Integer(5),-Integer(4)]) >>> L = IntegralLattice(V * G * V.T) >>> L.lll().gram_matrix() # needs sage.libs.gap [0 0 1] [0 7 0] [1 0 0] 
 - automorphisms(gens=None, is_finite=None)[source]¶
- Return the orthogonal group of this lattice as a matrix group. - The elements are isometries of the ambient vector space which preserve this lattice. They are represented by matrices with respect to the standard basis. - INPUT: - gens– list of matrices (default:- None)
- is_finite– boolean (default:- None); if set to- True, then the group is placed in the category of finite groups. Sage does not check this.
 - OUTPUT: - The matrix group generated by - gens. If- gensis not specified, then generators of the full orthogonal group of this lattice are computed. They are continued as the identity on the orthogonal complement of the lattice in its ambient space. Currently, we can only compute the orthogonal group for positive definite lattices.- EXAMPLES: - sage: A4 = IntegralLattice("A4") # needs sage.graphs sage: Aut = A4.orthogonal_group(); Aut # needs sage.graphs sage.libs.gap Group of isometries with 4 generators ( [0 0 0 1] [-1 -1 -1 0] [ 1 0 0 0] [ 1 0 0 0] [0 0 1 0] [ 0 0 0 -1] [-1 -1 -1 -1] [ 0 1 0 0] [0 1 0 0] [ 0 0 1 1] [ 0 0 0 1] [ 0 0 1 1] [1 0 0 0], [ 0 1 0 0], [ 0 0 1 0], [ 0 0 0 -1] ) - >>> from sage.all import * >>> A4 = IntegralLattice("A4") # needs sage.graphs >>> Aut = A4.orthogonal_group(); Aut # needs sage.graphs sage.libs.gap Group of isometries with 4 generators ( [0 0 0 1] [-1 -1 -1 0] [ 1 0 0 0] [ 1 0 0 0] [0 0 1 0] [ 0 0 0 -1] [-1 -1 -1 -1] [ 0 1 0 0] [0 1 0 0] [ 0 0 1 1] [ 0 0 0 1] [ 0 0 1 1] [1 0 0 0], [ 0 1 0 0], [ 0 0 1 0], [ 0 0 0 -1] ) - The group acts from the right on the lattice and its discriminant group: - sage: # needs sage.graphs sage.libs.gap sage: x = A4.an_element() sage: g = Aut.an_element(); g [-1 -1 -1 0] [ 0 0 1 0] [ 0 0 -1 -1] [ 0 1 1 1] sage: x*g (-1, -1, -1, 0) sage: (x*g).parent() == A4 True sage: (g*x).parent() Vector space of dimension 4 over Rational Field sage: y = A4.discriminant_group().an_element() sage: y*g (4) - >>> from sage.all import * >>> # needs sage.graphs sage.libs.gap >>> x = A4.an_element() >>> g = Aut.an_element(); g [-1 -1 -1 0] [ 0 0 1 0] [ 0 0 -1 -1] [ 0 1 1 1] >>> x*g (-1, -1, -1, 0) >>> (x*g).parent() == A4 True >>> (g*x).parent() Vector space of dimension 4 over Rational Field >>> y = A4.discriminant_group().an_element() >>> y*g (4) - If the group is finite we can compute the usual things: - sage: # needs sage.graphs sage.libs.gap sage: Aut.order() 240 sage: conj = Aut.conjugacy_classes_representatives() sage: len(conj) 14 sage: Aut.structure_description() 'C2 x S5' - >>> from sage.all import * >>> # needs sage.graphs sage.libs.gap >>> Aut.order() 240 >>> conj = Aut.conjugacy_classes_representatives() >>> len(conj) 14 >>> Aut.structure_description() 'C2 x S5' - The lattice can live in a larger ambient space: - sage: A2 = IntegralLattice(matrix.identity(3), ....: Matrix(ZZ, 2, 3, [1,-1,0,0,1,-1])) sage: A2.orthogonal_group() # needs sage.libs.gap Group of isometries with 2 generators ( [ 2/3 2/3 -1/3] [1 0 0] [ 2/3 -1/3 2/3] [0 0 1] [-1/3 2/3 2/3], [0 1 0] ) - >>> from sage.all import * >>> A2 = IntegralLattice(matrix.identity(Integer(3)), ... Matrix(ZZ, Integer(2), Integer(3), [Integer(1),-Integer(1),Integer(0),Integer(0),Integer(1),-Integer(1)])) >>> A2.orthogonal_group() # needs sage.libs.gap Group of isometries with 2 generators ( [ 2/3 2/3 -1/3] [1 0 0] [ 2/3 -1/3 2/3] [0 0 1] [-1/3 2/3 2/3], [0 1 0] ) - It can be negative definite as well: - sage: A2m = IntegralLattice(-Matrix(ZZ, 2, [2,1,1,2])) sage: G = A2m.orthogonal_group() # needs sage.libs.gap sage: G.order() # needs sage.libs.gap 12 - >>> from sage.all import * >>> A2m = IntegralLattice(-Matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),Integer(2)])) >>> G = A2m.orthogonal_group() # needs sage.libs.gap >>> G.order() # needs sage.libs.gap 12 - If the lattice is indefinite, sage does not know how to compute generators. Can you teach it?: - sage: U = IntegralLattice(Matrix(ZZ, 2, [0,1,1,0])) sage: U.orthogonal_group() # needs sage.libs.gap Traceback (most recent call last): ... NotImplementedError: currently, we can only compute generators for orthogonal groups over definite lattices. - >>> from sage.all import * >>> U = IntegralLattice(Matrix(ZZ, Integer(2), [Integer(0),Integer(1),Integer(1),Integer(0)])) >>> U.orthogonal_group() # needs sage.libs.gap Traceback (most recent call last): ... NotImplementedError: currently, we can only compute generators for orthogonal groups over definite lattices. - But we can define subgroups: - sage: S = IntegralLattice(Matrix(ZZ, 2, [2, 3, 3, 2])) sage: f = Matrix(ZZ, 2, [0,1,-1,3]) sage: S.orthogonal_group([f]) # needs sage.libs.gap Group of isometries with 1 generator ( [ 0 1] [-1 3] ) - >>> from sage.all import * >>> S = IntegralLattice(Matrix(ZZ, Integer(2), [Integer(2), Integer(3), Integer(3), Integer(2)])) >>> f = Matrix(ZZ, Integer(2), [Integer(0),Integer(1),-Integer(1),Integer(3)]) >>> S.orthogonal_group([f]) # needs sage.libs.gap Group of isometries with 1 generator ( [ 0 1] [-1 3] ) 
 - direct_sum(M)[source]¶
- Return the direct sum of this lattice with - M.- INPUT: - M– a module over \(\ZZ\)
 - EXAMPLES: - sage: A = IntegralLattice(1) sage: A.direct_sum(A) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Standard scalar product - >>> from sage.all import * >>> A = IntegralLattice(Integer(1)) >>> A.direct_sum(A) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Standard scalar product 
 - discriminant_group(s=0)[source]¶
- Return the discriminant group \(L^\vee / L\) of this lattice. - INPUT: - s– integer (default: 0)
 - OUTPUT: - The \(s\) primary part of the discriminant group. If \(s=0\), returns the whole discriminant group. - EXAMPLES: - sage: L = IntegralLattice(Matrix(ZZ, 2, 2, [2,1,1,-2]) * 2) sage: L.discriminant_group() Finite quadratic module over Integer Ring with invariants (2, 10) Gram matrix of the quadratic form with values in Q/2Z: [ 1 1/2] [1/2 1/5] sage: L.discriminant_group(2) 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] sage: L.discriminant_group(5) Finite quadratic module over Integer Ring with invariants (5,) Gram matrix of the quadratic form with values in Q/2Z: [4/5] - >>> from sage.all import * >>> L = IntegralLattice(Matrix(ZZ, Integer(2), Integer(2), [Integer(2),Integer(1),Integer(1),-Integer(2)]) * Integer(2)) >>> L.discriminant_group() Finite quadratic module over Integer Ring with invariants (2, 10) Gram matrix of the quadratic form with values in Q/2Z: [ 1 1/2] [1/2 1/5] >>> L.discriminant_group(Integer(2)) 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] >>> L.discriminant_group(Integer(5)) Finite quadratic module over Integer Ring with invariants (5,) Gram matrix of the quadratic form with values in Q/2Z: [4/5] 
 - dual_lattice()[source]¶
- Return the dual lattice as a - FreeQuadraticModule.- Let \(L\) be a lattice. Its dual lattice is \[L^\vee = \{x \in L \otimes \QQ : (x, l) \in \ZZ \; \forall l \in L \}.\]- EXAMPLES: - sage: L = IntegralLattice("A2") # needs sage.graphs sage: Ldual = L.dual_lattice(); Ldual # needs sage.graphs Free module of degree 2 and rank 2 over Integer Ring Echelon basis matrix: [1/3 2/3] [ 0 1] - >>> from sage.all import * >>> L = IntegralLattice("A2") # needs sage.graphs >>> Ldual = L.dual_lattice(); Ldual # needs sage.graphs Free module of degree 2 and rank 2 over Integer Ring Echelon basis matrix: [1/3 2/3] [ 0 1] - Since our lattices are always integral, a lattice is contained in its dual: - sage: L.is_submodule(Ldual) # needs sage.graphs True - >>> from sage.all import * >>> L.is_submodule(Ldual) # needs sage.graphs True 
 - enumerate_close_vectors(target)[source]¶
- Return an iterator over all the vectors in this lattice, starting from vectors relatively close to the given - targetvector.- Warning - The returned vectors are not necessarily ordered strictly by their distance to the target. - EXAMPLES: - sage: L = IntegralLattice(4, [[1,2,3,4], [7,7,8,8], [1,-1,1,0]]) sage: t = vector([1/2, -133/7, 123.44, -11]) sage: close = L.enumerate_close_vectors(t) sage: vecs = [next(close) for _ in range(10)] sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v)) [(-1, -16, 121, 148), (0, -17, 122, 148), (-3, -22, 122, 148), (1, -18, 123, 148), (-2, -23, 123, 148), (2, -19, 124, 148), (3, -20, 125, 148), (4, -21, 126, 148), (-3, -19, 124, 152), (-2, -20, 125, 152)] - >>> from sage.all import * >>> L = IntegralLattice(Integer(4), [[Integer(1),Integer(2),Integer(3),Integer(4)], [Integer(7),Integer(7),Integer(8),Integer(8)], [Integer(1),-Integer(1),Integer(1),Integer(0)]]) >>> t = vector([Integer(1)/Integer(2), -Integer(133)/Integer(7), RealNumber('123.44'), -Integer(11)]) >>> close = L.enumerate_close_vectors(t) >>> vecs = [next(close) for _ in range(Integer(10))] >>> sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v)) [(-1, -16, 121, 148), (0, -17, 122, 148), (-3, -22, 122, 148), (1, -18, 123, 148), (-2, -23, 123, 148), (2, -19, 124, 148), (3, -20, 125, 148), (4, -21, 126, 148), (-3, -19, 124, 152), (-2, -20, 125, 152)] 
 - enumerate_short_vectors()[source]¶
- Return an iterator over all the vectors in this lattice (modulo sign), starting from shorter vectors. - Warning - The returned vectors are not necessarily ordered strictly by length. - EXAMPLES: - sage: L = IntegralLattice(4, [[1,2,3,4], [7,7,8,8], [1,-1,1,0]]) sage: short = L.enumerate_short_vectors() sage: vecs = [next(short) for _ in range(20)] sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v)) [(1, -1, 1, 0), (2, -2, 2, 0), (3, -3, 3, 0), (0, 3, 2, 4), (1, 2, 3, 4), (3, 2, -2, -4), (4, 4, 1, 0), (-1, 4, 1, 4), (3, 5, 0, 0), (4, 1, -1, -4), (2, 1, 4, 4), (2, 3, -3, -4), (5, 3, 2, 0), (2, 6, -1, 0), (5, 0, 0, -4), (-2, 5, 0, 4), (4, -4, 4, 0), (1, 4, -4, -4), (6, 2, 3, 0), (3, 0, 5, 4)] - >>> from sage.all import * >>> L = IntegralLattice(Integer(4), [[Integer(1),Integer(2),Integer(3),Integer(4)], [Integer(7),Integer(7),Integer(8),Integer(8)], [Integer(1),-Integer(1),Integer(1),Integer(0)]]) >>> short = L.enumerate_short_vectors() >>> vecs = [next(short) for _ in range(Integer(20))] >>> sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v)) [(1, -1, 1, 0), (2, -2, 2, 0), (3, -3, 3, 0), (0, 3, 2, 4), (1, 2, 3, 4), (3, 2, -2, -4), (4, 4, 1, 0), (-1, 4, 1, 4), (3, 5, 0, 0), (4, 1, -1, -4), (2, 1, 4, 4), (2, 3, -3, -4), (5, 3, 2, 0), (2, 6, -1, 0), (5, 0, 0, -4), (-2, 5, 0, 4), (4, -4, 4, 0), (1, 4, -4, -4), (6, 2, 3, 0), (3, 0, 5, 4)] - This example demonstrates that the lattice inner product is used for the norm: - sage: Q = Matrix(QQ, [[1000, 0], [0, 1]]) sage: B = [[1, 1], [1, -1]] sage: L = IntegralLattice(Q, basis=B) sage: short = L.enumerate_short_vectors() sage: vecs = [next(short) for _ in range(20)] sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v)) [(0, -2), (0, -4), (0, -6), (0, -8), (0, -10), (0, -12), (0, -14), (0, -16), (0, -18), (0, -20), (0, -22), (0, -24), (0, -26), (0, -28), (0, -30), (-1, -1), (-1, 1), (-1, -3), (-1, 3), (0, -32)] - >>> from sage.all import * >>> Q = Matrix(QQ, [[Integer(1000), Integer(0)], [Integer(0), Integer(1)]]) >>> B = [[Integer(1), Integer(1)], [Integer(1), -Integer(1)]] >>> L = IntegralLattice(Q, basis=B) >>> short = L.enumerate_short_vectors() >>> vecs = [next(short) for _ in range(Integer(20))] >>> sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v)) [(0, -2), (0, -4), (0, -6), (0, -8), (0, -10), (0, -12), (0, -14), (0, -16), (0, -18), (0, -20), (0, -22), (0, -24), (0, -26), (0, -28), (0, -30), (-1, -1), (-1, 1), (-1, -3), (-1, 3), (0, -32)] 
 - genus()[source]¶
- Return the genus of this lattice. - EXAMPLES: - sage: L = IntegralLattice("U") sage: L.genus() # needs sage.padics Genus of [0 1] [1 0] Signature: (1, 1) Genus symbol at 2: 1^2 - >>> from sage.all import * >>> L = IntegralLattice("U") >>> L.genus() # needs sage.padics Genus of [0 1] [1 0] Signature: (1, 1) Genus symbol at 2: 1^2 
 - is_even()[source]¶
- Return whether the diagonal entries of the Gram matrix are even. - EXAMPLES: - sage: G = Matrix(ZZ, 2, 2, [-1,1,1,2]) sage: L = IntegralLattice(G) sage: L.is_even() False sage: L = IntegralLattice("A2") # needs sage.graphs sage: L.is_even() # needs sage.graphs True - >>> from sage.all import * >>> G = Matrix(ZZ, Integer(2), Integer(2), [-Integer(1),Integer(1),Integer(1),Integer(2)]) >>> L = IntegralLattice(G) >>> L.is_even() False >>> L = IntegralLattice("A2") # needs sage.graphs >>> L.is_even() # needs sage.graphs True 
 - is_primitive(M)[source]¶
- Return whether - Mis a primitive submodule of this lattice.- A \(\ZZ\)-submodule - Mof a \(\ZZ\)-module- Lis called primitive if the quotient- L/Mis torsion free.- INPUT: - M– a submodule of this lattice
 - EXAMPLES: - sage: U = IntegralLattice("U") sage: L1 = U.span([vector([1,1])]) sage: L2 = U.span([vector([1,-1])]) sage: U.is_primitive(L1) True sage: U.is_primitive(L2) True sage: U.is_primitive(L1 + L2) False - >>> from sage.all import * >>> U = IntegralLattice("U") >>> L1 = U.span([vector([Integer(1),Integer(1)])]) >>> L2 = U.span([vector([Integer(1),-Integer(1)])]) >>> U.is_primitive(L1) True >>> U.is_primitive(L2) True >>> U.is_primitive(L1 + L2) False - We can also compute the index: - sage: (L1 + L2).index_in(U) 2 - >>> from sage.all import * >>> (L1 + L2).index_in(U) 2 
 - lll()[source]¶
- Return this lattice with an LLL reduced basis. - EXAMPLES: - sage: L = IntegralLattice('A2') # needs sage.graphs sage: L.lll() == L # needs sage.graphs sage.libs.pari True sage: G = matrix(ZZ, 3, [0,1,0, 1,0,0, 0,0,7]) sage: V = matrix(ZZ, 3, [-14,-15,-15, -4,1,16, -5,-5,-4]) sage: L = IntegralLattice(V * G * V.T) sage: L.lll().gram_matrix() # needs sage.libs.gap [0 0 1] [0 7 0] [1 0 0] - >>> from sage.all import * >>> L = IntegralLattice('A2') # needs sage.graphs >>> L.lll() == L # needs sage.graphs sage.libs.pari True >>> G = matrix(ZZ, Integer(3), [Integer(0),Integer(1),Integer(0), Integer(1),Integer(0),Integer(0), Integer(0),Integer(0),Integer(7)]) >>> V = matrix(ZZ, Integer(3), [-Integer(14),-Integer(15),-Integer(15), -Integer(4),Integer(1),Integer(16), -Integer(5),-Integer(5),-Integer(4)]) >>> L = IntegralLattice(V * G * V.T) >>> L.lll().gram_matrix() # needs sage.libs.gap [0 0 1] [0 7 0] [1 0 0] 
 - max()[source]¶
- Return the maximum of this lattice. \[\max\{x^2 | x \in L\setminus \{0\}\}\]- EXAMPLES: - sage: L = IntegralLattice('A2') # needs sage.graphs sage: L.maximum() # needs sage.graphs +Infinity sage: L.twist(-1).maximum() # needs sage.graphs sage.libs.pari -2 - >>> from sage.all import * >>> L = IntegralLattice('A2') # needs sage.graphs >>> L.maximum() # needs sage.graphs +Infinity >>> L.twist(-Integer(1)).maximum() # needs sage.graphs sage.libs.pari -2 
 - maximal_overlattice(p=None)[source]¶
- Return a maximal even integral overlattice of this lattice. - INPUT: - p– (default:- None) if given return an overlattice \(M\) of this lattice \(L\) that is maximal at \(p\) and the completions \(M_q = L_q\) are equal for all primes \(q \neq p\)
 - If \(p\) is \(2\) or - None, then the lattice must be even.- EXAMPLES: - sage: # needs sage.graphs sage.libs.pari sage: L = IntegralLattice("A4").twist(25*89) sage: L.maximal_overlattice().determinant() 5 sage: L.maximal_overlattice(89).determinant().factor() 5^9 sage: L.maximal_overlattice(5).determinant().factor() 5 * 89^4 - >>> from sage.all import * >>> # needs sage.graphs sage.libs.pari >>> L = IntegralLattice("A4").twist(Integer(25)*Integer(89)) >>> L.maximal_overlattice().determinant() 5 >>> L.maximal_overlattice(Integer(89)).determinant().factor() 5^9 >>> L.maximal_overlattice(Integer(5)).determinant().factor() 5 * 89^4 
 - maximum()[source]¶
- Return the maximum of this lattice. \[\max\{x^2 | x \in L\setminus \{0\}\}\]- EXAMPLES: - sage: L = IntegralLattice('A2') # needs sage.graphs sage: L.maximum() # needs sage.graphs +Infinity sage: L.twist(-1).maximum() # needs sage.graphs sage.libs.pari -2 - >>> from sage.all import * >>> L = IntegralLattice('A2') # needs sage.graphs >>> L.maximum() # needs sage.graphs +Infinity >>> L.twist(-Integer(1)).maximum() # needs sage.graphs sage.libs.pari -2 
 - min()[source]¶
- Return the minimum of this lattice. \[\min\{x^2 | x \in L\setminus \{0\}\}\]- EXAMPLES: - sage: L = IntegralLattice('A2') # needs sage.graphs sage: L.minimum() # needs sage.graphs 2 sage: L.twist(-1).minimum() # needs sage.graphs -Infinity - >>> from sage.all import * >>> L = IntegralLattice('A2') # needs sage.graphs >>> L.minimum() # needs sage.graphs 2 >>> L.twist(-Integer(1)).minimum() # needs sage.graphs -Infinity 
 - minimum()[source]¶
- Return the minimum of this lattice. \[\min\{x^2 | x \in L\setminus \{0\}\}\]- EXAMPLES: - sage: L = IntegralLattice('A2') # needs sage.graphs sage: L.minimum() # needs sage.graphs 2 sage: L.twist(-1).minimum() # needs sage.graphs -Infinity - >>> from sage.all import * >>> L = IntegralLattice('A2') # needs sage.graphs >>> L.minimum() # needs sage.graphs 2 >>> L.twist(-Integer(1)).minimum() # needs sage.graphs -Infinity 
 - orthogonal_complement(M)[source]¶
- Return the orthogonal complement of - Min this lattice.- INPUT: - M– a module in the same ambient space or a list of elements of the ambient space
 - EXAMPLES: - sage: H5 = Matrix(ZZ, 2, [2,1,1,-2]) sage: L = IntegralLattice(H5) sage: S = L.span([vector([1,1])]) sage: L.orthogonal_complement(S) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 3] Inner product matrix: [ 2 1] [ 1 -2] sage: L = IntegralLattice(2) sage: L.orthogonal_complement([vector(ZZ, [1,0])]) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [0 1] Standard scalar product - >>> from sage.all import * >>> H5 = Matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),-Integer(2)]) >>> L = IntegralLattice(H5) >>> S = L.span([vector([Integer(1),Integer(1)])]) >>> L.orthogonal_complement(S) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 3] Inner product matrix: [ 2 1] [ 1 -2] >>> L = IntegralLattice(Integer(2)) >>> L.orthogonal_complement([vector(ZZ, [Integer(1),Integer(0)])]) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [0 1] Standard scalar product 
 - orthogonal_group(gens=None, is_finite=None)[source]¶
- Return the orthogonal group of this lattice as a matrix group. - The elements are isometries of the ambient vector space which preserve this lattice. They are represented by matrices with respect to the standard basis. - INPUT: - gens– list of matrices (default:- None)
- is_finite– boolean (default:- None); if set to- True, then the group is placed in the category of finite groups. Sage does not check this.
 - OUTPUT: - The matrix group generated by - gens. If- gensis not specified, then generators of the full orthogonal group of this lattice are computed. They are continued as the identity on the orthogonal complement of the lattice in its ambient space. Currently, we can only compute the orthogonal group for positive definite lattices.- EXAMPLES: - sage: A4 = IntegralLattice("A4") # needs sage.graphs sage: Aut = A4.orthogonal_group(); Aut # needs sage.graphs sage.libs.gap Group of isometries with 4 generators ( [0 0 0 1] [-1 -1 -1 0] [ 1 0 0 0] [ 1 0 0 0] [0 0 1 0] [ 0 0 0 -1] [-1 -1 -1 -1] [ 0 1 0 0] [0 1 0 0] [ 0 0 1 1] [ 0 0 0 1] [ 0 0 1 1] [1 0 0 0], [ 0 1 0 0], [ 0 0 1 0], [ 0 0 0 -1] ) - >>> from sage.all import * >>> A4 = IntegralLattice("A4") # needs sage.graphs >>> Aut = A4.orthogonal_group(); Aut # needs sage.graphs sage.libs.gap Group of isometries with 4 generators ( [0 0 0 1] [-1 -1 -1 0] [ 1 0 0 0] [ 1 0 0 0] [0 0 1 0] [ 0 0 0 -1] [-1 -1 -1 -1] [ 0 1 0 0] [0 1 0 0] [ 0 0 1 1] [ 0 0 0 1] [ 0 0 1 1] [1 0 0 0], [ 0 1 0 0], [ 0 0 1 0], [ 0 0 0 -1] ) - The group acts from the right on the lattice and its discriminant group: - sage: # needs sage.graphs sage.libs.gap sage: x = A4.an_element() sage: g = Aut.an_element(); g [-1 -1 -1 0] [ 0 0 1 0] [ 0 0 -1 -1] [ 0 1 1 1] sage: x*g (-1, -1, -1, 0) sage: (x*g).parent() == A4 True sage: (g*x).parent() Vector space of dimension 4 over Rational Field sage: y = A4.discriminant_group().an_element() sage: y*g (4) - >>> from sage.all import * >>> # needs sage.graphs sage.libs.gap >>> x = A4.an_element() >>> g = Aut.an_element(); g [-1 -1 -1 0] [ 0 0 1 0] [ 0 0 -1 -1] [ 0 1 1 1] >>> x*g (-1, -1, -1, 0) >>> (x*g).parent() == A4 True >>> (g*x).parent() Vector space of dimension 4 over Rational Field >>> y = A4.discriminant_group().an_element() >>> y*g (4) - If the group is finite we can compute the usual things: - sage: # needs sage.graphs sage.libs.gap sage: Aut.order() 240 sage: conj = Aut.conjugacy_classes_representatives() sage: len(conj) 14 sage: Aut.structure_description() 'C2 x S5' - >>> from sage.all import * >>> # needs sage.graphs sage.libs.gap >>> Aut.order() 240 >>> conj = Aut.conjugacy_classes_representatives() >>> len(conj) 14 >>> Aut.structure_description() 'C2 x S5' - The lattice can live in a larger ambient space: - sage: A2 = IntegralLattice(matrix.identity(3), ....: Matrix(ZZ, 2, 3, [1,-1,0,0,1,-1])) sage: A2.orthogonal_group() # needs sage.libs.gap Group of isometries with 2 generators ( [ 2/3 2/3 -1/3] [1 0 0] [ 2/3 -1/3 2/3] [0 0 1] [-1/3 2/3 2/3], [0 1 0] ) - >>> from sage.all import * >>> A2 = IntegralLattice(matrix.identity(Integer(3)), ... Matrix(ZZ, Integer(2), Integer(3), [Integer(1),-Integer(1),Integer(0),Integer(0),Integer(1),-Integer(1)])) >>> A2.orthogonal_group() # needs sage.libs.gap Group of isometries with 2 generators ( [ 2/3 2/3 -1/3] [1 0 0] [ 2/3 -1/3 2/3] [0 0 1] [-1/3 2/3 2/3], [0 1 0] ) - It can be negative definite as well: - sage: A2m = IntegralLattice(-Matrix(ZZ, 2, [2,1,1,2])) sage: G = A2m.orthogonal_group() # needs sage.libs.gap sage: G.order() # needs sage.libs.gap 12 - >>> from sage.all import * >>> A2m = IntegralLattice(-Matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),Integer(2)])) >>> G = A2m.orthogonal_group() # needs sage.libs.gap >>> G.order() # needs sage.libs.gap 12 - If the lattice is indefinite, sage does not know how to compute generators. Can you teach it?: - sage: U = IntegralLattice(Matrix(ZZ, 2, [0,1,1,0])) sage: U.orthogonal_group() # needs sage.libs.gap Traceback (most recent call last): ... NotImplementedError: currently, we can only compute generators for orthogonal groups over definite lattices. - >>> from sage.all import * >>> U = IntegralLattice(Matrix(ZZ, Integer(2), [Integer(0),Integer(1),Integer(1),Integer(0)])) >>> U.orthogonal_group() # needs sage.libs.gap Traceback (most recent call last): ... NotImplementedError: currently, we can only compute generators for orthogonal groups over definite lattices. - But we can define subgroups: - sage: S = IntegralLattice(Matrix(ZZ, 2, [2, 3, 3, 2])) sage: f = Matrix(ZZ, 2, [0,1,-1,3]) sage: S.orthogonal_group([f]) # needs sage.libs.gap Group of isometries with 1 generator ( [ 0 1] [-1 3] ) - >>> from sage.all import * >>> S = IntegralLattice(Matrix(ZZ, Integer(2), [Integer(2), Integer(3), Integer(3), Integer(2)])) >>> f = Matrix(ZZ, Integer(2), [Integer(0),Integer(1),-Integer(1),Integer(3)]) >>> S.orthogonal_group([f]) # needs sage.libs.gap Group of isometries with 1 generator ( [ 0 1] [-1 3] ) 
 - overlattice(gens)[source]¶
- Return the lattice spanned by this lattice and - gens.- INPUT: - gens– list of elements or a rational matrix
 - EXAMPLES: - sage: L = IntegralLattice(Matrix(ZZ, 2, 2, [2,0,0,2])) sage: M = L.overlattice([vector([1,1])/2]) sage: M.gram_matrix() [1 1] [1 2] - >>> from sage.all import * >>> L = IntegralLattice(Matrix(ZZ, Integer(2), Integer(2), [Integer(2),Integer(0),Integer(0),Integer(2)])) >>> M = L.overlattice([vector([Integer(1),Integer(1)])/Integer(2)]) >>> M.gram_matrix() [1 1] [1 2] 
 - quadratic_form()[source]¶
- Return the quadratic form given by \(q(x)=(x,x)\). - EXAMPLES: - sage: L = IntegralLattice("A2") # needs sage.graphs sage: q = L.quadratic_form(); q # needs sage.graphs Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 -2 ] [ * 2 ] - >>> from sage.all import * >>> L = IntegralLattice("A2") # needs sage.graphs >>> q = L.quadratic_form(); q # needs sage.graphs Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 -2 ] [ * 2 ] 
 - short_vectors(n, **kwargs)[source]¶
- Return the short vectors of length \(< n\). - INPUT: - n– integer
- further keyword arguments are passed on to - sage.quadratic_forms.short_vector_list_up_to_length()
 - OUTPUT: list \(L\) where - L[k]is the list of vectors of lengths \(k\)- EXAMPLES: - sage: A2 = IntegralLattice('A2') # needs sage.graphs sage: A2.short_vectors(3) # needs sage.graphs sage.libs.pari [[(0, 0)], [], [(1, 1), (-1, -1), (0, 1), (0, -1), (1, 0), (-1, 0)]] sage: A2.short_vectors(3, up_to_sign_flag=True) # needs sage.graphs sage.libs.pari [[(0, 0)], [], [(1, 1), (0, 1), (1, 0)]] - >>> from sage.all import * >>> A2 = IntegralLattice('A2') # needs sage.graphs >>> A2.short_vectors(Integer(3)) # needs sage.graphs sage.libs.pari [[(0, 0)], [], [(1, 1), (-1, -1), (0, 1), (0, -1), (1, 0), (-1, 0)]] >>> A2.short_vectors(Integer(3), up_to_sign_flag=True) # needs sage.graphs sage.libs.pari [[(0, 0)], [], [(1, 1), (0, 1), (1, 0)]] 
 - signature()[source]¶
- Return the signature of this lattice, which is defined as the difference between the number of positive eigenvalues and the number of negative eigenvalues in the Gram matrix. - EXAMPLES: - sage: U = IntegralLattice("U") sage: U.signature() 0 - >>> from sage.all import * >>> U = IntegralLattice("U") >>> U.signature() 0 
 - signature_pair()[source]¶
- Return the signature tuple \((n_+,n_-)\) of this lattice. - Here \(n_+\) (resp. \(n_-\)) is the number of positive (resp. negative) eigenvalues of the Gram matrix. - EXAMPLES: - sage: A2 = IntegralLattice("A2") # needs sage.graphs sage: A2.signature_pair() # needs sage.graphs (2, 0) - >>> from sage.all import * >>> A2 = IntegralLattice("A2") # needs sage.graphs >>> A2.signature_pair() # needs sage.graphs (2, 0) 
 - sublattice(basis)[source]¶
- Return the sublattice spanned by - basis.- INPUT: - basis– list of elements of this lattice
 - EXAMPLES: - sage: U = IntegralLattice("U") sage: S = U.sublattice([vector([1,1])]); S Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [0 1] [1 0] sage: U.sublattice([vector([1,-1])/2]) Traceback (most recent call last): ... ValueError: lattices must be integral; use FreeQuadraticModule instead sage: S.sublattice([vector([1,-1])]) Traceback (most recent call last): ... ValueError: the basis (= [(1, -1)]) does not span a submodule - >>> from sage.all import * >>> U = IntegralLattice("U") >>> S = U.sublattice([vector([Integer(1),Integer(1)])]); S Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [0 1] [1 0] >>> U.sublattice([vector([Integer(1),-Integer(1)])/Integer(2)]) Traceback (most recent call last): ... ValueError: lattices must be integral; use FreeQuadraticModule instead >>> S.sublattice([vector([Integer(1),-Integer(1)])]) Traceback (most recent call last): ... ValueError: the basis (= [(1, -1)]) does not span a submodule 
 - tensor_product(other, discard_basis=False)[source]¶
- Return the tensor product of - selfand- other.- INPUT: - other– an integral lattice
- discard_basis– boolean (default:- False); if- True, then the lattice returned is equipped with the standard basis
 - EXAMPLES: - sage: # needs sage.graphs sage: L = IntegralLattice("D3", [[1,-1,0], [0,1,-1]]) sage: L1 = L.tensor_product(L); L1 Lattice of degree 9 and rank 4 over Integer Ring Basis matrix: [ 1 -1 0 -1 1 0 0 0 0] [ 0 1 -1 0 -1 1 0 0 0] [ 0 0 0 1 -1 0 -1 1 0] [ 0 0 0 0 1 -1 0 -1 1] Inner product matrix: [ 4 -2 -2 -2 1 1 -2 1 1] [-2 4 0 1 -2 0 1 -2 0] [-2 0 4 1 0 -2 1 0 -2] [-2 1 1 4 -2 -2 0 0 0] [ 1 -2 0 -2 4 0 0 0 0] [ 1 0 -2 -2 0 4 0 0 0] [-2 1 1 0 0 0 4 -2 -2] [ 1 -2 0 0 0 0 -2 4 0] [ 1 0 -2 0 0 0 -2 0 4] sage: L1.gram_matrix() [ 36 -12 -12 4] [-12 24 4 -8] [-12 4 24 -8] [ 4 -8 -8 16] sage: L2 = L.tensor_product(L, True); L2 Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: [ 36 -12 -12 4] [-12 24 4 -8] [-12 4 24 -8] [ 4 -8 -8 16] - >>> from sage.all import * >>> # needs sage.graphs >>> L = IntegralLattice("D3", [[Integer(1),-Integer(1),Integer(0)], [Integer(0),Integer(1),-Integer(1)]]) >>> L1 = L.tensor_product(L); L1 Lattice of degree 9 and rank 4 over Integer Ring Basis matrix: [ 1 -1 0 -1 1 0 0 0 0] [ 0 1 -1 0 -1 1 0 0 0] [ 0 0 0 1 -1 0 -1 1 0] [ 0 0 0 0 1 -1 0 -1 1] Inner product matrix: [ 4 -2 -2 -2 1 1 -2 1 1] [-2 4 0 1 -2 0 1 -2 0] [-2 0 4 1 0 -2 1 0 -2] [-2 1 1 4 -2 -2 0 0 0] [ 1 -2 0 -2 4 0 0 0 0] [ 1 0 -2 -2 0 4 0 0 0] [-2 1 1 0 0 0 4 -2 -2] [ 1 -2 0 0 0 0 -2 4 0] [ 1 0 -2 0 0 0 -2 0 4] >>> L1.gram_matrix() [ 36 -12 -12 4] [-12 24 4 -8] [-12 4 24 -8] [ 4 -8 -8 16] >>> L2 = L.tensor_product(L, True); L2 Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: [ 36 -12 -12 4] [-12 24 4 -8] [-12 4 24 -8] [ 4 -8 -8 16] 
 - twist(s, discard_basis=False)[source]¶
- Return the lattice with inner product matrix scaled by - s.- INPUT: - s– nonzero integer
- discard_basis– boolean (default:- False); if- True, then the lattice returned is equipped with the standard basis
 - EXAMPLES: - sage: L = IntegralLattice("A4") # needs sage.graphs sage: L.twist(3) # needs sage.graphs Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: [ 6 -3 0 0] [-3 6 -3 0] [ 0 -3 6 -3] [ 0 0 -3 6] sage: L = IntegralLattice(3, [[2,1,0], [0,1,1]]); L Lattice of degree 3 and rank 2 over Integer Ring Basis matrix: [2 1 0] [0 1 1] Standard scalar product sage: L.twist(1) Lattice of degree 3 and rank 2 over Integer Ring Basis matrix: [2 1 0] [0 1 1] Standard scalar product sage: L.twist(1, True) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [5 1] [1 2] - >>> from sage.all import * >>> L = IntegralLattice("A4") # needs sage.graphs >>> L.twist(Integer(3)) # needs sage.graphs Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: [ 6 -3 0 0] [-3 6 -3 0] [ 0 -3 6 -3] [ 0 0 -3 6] >>> L = IntegralLattice(Integer(3), [[Integer(2),Integer(1),Integer(0)], [Integer(0),Integer(1),Integer(1)]]); L Lattice of degree 3 and rank 2 over Integer Ring Basis matrix: [2 1 0] [0 1 1] Standard scalar product >>> L.twist(Integer(1)) Lattice of degree 3 and rank 2 over Integer Ring Basis matrix: [2 1 0] [0 1 1] Standard scalar product >>> L.twist(Integer(1), True) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [5 1] [1 2] 
 
- sage.modules.free_quadratic_module_integer_symmetric.IntegralLattice(data, basis=None)[source]¶
- Return the integral lattice spanned by - basisin the ambient space.- A lattice is a finitely generated free abelian group \(L \cong \ZZ^r\) equipped with a non-degenerate, symmetric bilinear form \(L \times L \colon \rightarrow \ZZ\). Here, lattices have an ambient quadratic space \(\QQ^n\) and a distinguished basis. - INPUT: - The input is a descriptor of the lattice and a (optional) basis. - - data– can be one of the following:- a symmetric matrix over the rationals – the inner product matrix 
- an integer – the dimension for a Euclidean lattice 
- a symmetric Cartan type or anything recognized by - CartanMatrix(see also- Cartan types) – for a root lattice
- the string - 'U'or- 'H'– for hyperbolic lattices
 - basis– (optional) a matrix whose rows form a basis of the lattice, or a list of module elements forming a basis
 - OUTPUT: - A lattice in the ambient space defined by the inner_product_matrix. Unless specified, the basis of the lattice is the standard basis. - EXAMPLES: - sage: H5 = Matrix(ZZ, 2, [2,1,1,-2]) sage: IntegralLattice(H5) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [ 2 1] [ 1 -2] - >>> from sage.all import * >>> H5 = Matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),-Integer(2)]) >>> IntegralLattice(H5) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [ 2 1] [ 1 -2] - A basis can be specified too: - sage: IntegralLattice(H5, Matrix([1,1])) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [ 2 1] [ 1 -2] - >>> from sage.all import * >>> IntegralLattice(H5, Matrix([Integer(1),Integer(1)])) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [ 2 1] [ 1 -2] - We can define a Euclidean lattice just by its dimension: - sage: IntegralLattice(3) Lattice of degree 3 and rank 3 over Integer Ring Standard basis Standard scalar product - >>> from sage.all import * >>> IntegralLattice(Integer(3)) Lattice of degree 3 and rank 3 over Integer Ring Standard basis Standard scalar product - Here is an example of the \(A_2\) root lattice in Euclidean space: - sage: basis = Matrix([[1,-1,0], [0,1,-1]]) sage: A2 = IntegralLattice(3, basis) sage: A2 Lattice of degree 3 and rank 2 over Integer Ring Basis matrix: [ 1 -1 0] [ 0 1 -1] Standard scalar product sage: A2.gram_matrix() [ 2 -1] [-1 2] - >>> from sage.all import * >>> basis = Matrix([[Integer(1),-Integer(1),Integer(0)], [Integer(0),Integer(1),-Integer(1)]]) >>> A2 = IntegralLattice(Integer(3), basis) >>> A2 Lattice of degree 3 and rank 2 over Integer Ring Basis matrix: [ 1 -1 0] [ 0 1 -1] Standard scalar product >>> A2.gram_matrix() [ 2 -1] [-1 2] - We use - 'U'or- 'H'for defining a hyperbolic lattice:- sage: L1 = IntegralLattice('U') sage: L1 Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [0 1] [1 0] sage: L1 == IntegralLattice('H') True - >>> from sage.all import * >>> L1 = IntegralLattice('U') >>> L1 Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [0 1] [1 0] >>> L1 == IntegralLattice('H') True - We can construct root lattices by specifying their type (see - Cartan typesand- CartanMatrix):- sage: # needs sage.graphs sage: IntegralLattice(["E", 7]) Lattice of degree 7 and rank 7 over Integer Ring Standard basis Inner product matrix: [ 2 0 -1 0 0 0 0] [ 0 2 0 -1 0 0 0] [-1 0 2 -1 0 0 0] [ 0 -1 -1 2 -1 0 0] [ 0 0 0 -1 2 -1 0] [ 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 -1 2] sage: IntegralLattice(["A", 2]) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [ 2 -1] [-1 2] sage: IntegralLattice("D3") Lattice of degree 3 and rank 3 over Integer Ring Standard basis Inner product matrix: [ 2 -1 -1] [-1 2 0] [-1 0 2] sage: IntegralLattice(["D", 4]) Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: [ 2 -1 0 0] [-1 2 -1 -1] [ 0 -1 2 0] [ 0 -1 0 2] - >>> from sage.all import * >>> # needs sage.graphs >>> IntegralLattice(["E", Integer(7)]) Lattice of degree 7 and rank 7 over Integer Ring Standard basis Inner product matrix: [ 2 0 -1 0 0 0 0] [ 0 2 0 -1 0 0 0] [-1 0 2 -1 0 0 0] [ 0 -1 -1 2 -1 0 0] [ 0 0 0 -1 2 -1 0] [ 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 -1 2] >>> IntegralLattice(["A", Integer(2)]) Lattice of degree 2 and rank 2 over Integer Ring Standard basis Inner product matrix: [ 2 -1] [-1 2] >>> IntegralLattice("D3") Lattice of degree 3 and rank 3 over Integer Ring Standard basis Inner product matrix: [ 2 -1 -1] [-1 2 0] [-1 0 2] >>> IntegralLattice(["D", Integer(4)]) Lattice of degree 4 and rank 4 over Integer Ring Standard basis Inner product matrix: [ 2 -1 0 0] [-1 2 -1 -1] [ 0 -1 2 0] [ 0 -1 0 2] - We can specify a basis as well: - sage: G = Matrix(ZZ, 2, [0,1,1,0]) sage: B = [vector([1,1])] sage: IntegralLattice(G, basis=B) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [0 1] [1 0] sage: IntegralLattice(["A", 3], [[1,1,1]]) # needs sage.graphs Lattice of degree 3 and rank 1 over Integer Ring Basis matrix: [1 1 1] Inner product matrix: [ 2 -1 0] [-1 2 -1] [ 0 -1 2] sage: IntegralLattice(4, [[1,1,1,1]]) Lattice of degree 4 and rank 1 over Integer Ring Basis matrix: [1 1 1 1] Standard scalar product sage: IntegralLattice("A2", [[1,1]]) # needs sage.graphs Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [ 2 -1] [-1 2] - >>> from sage.all import * >>> G = Matrix(ZZ, Integer(2), [Integer(0),Integer(1),Integer(1),Integer(0)]) >>> B = [vector([Integer(1),Integer(1)])] >>> IntegralLattice(G, basis=B) Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [0 1] [1 0] >>> IntegralLattice(["A", Integer(3)], [[Integer(1),Integer(1),Integer(1)]]) # needs sage.graphs Lattice of degree 3 and rank 1 over Integer Ring Basis matrix: [1 1 1] Inner product matrix: [ 2 -1 0] [-1 2 -1] [ 0 -1 2] >>> IntegralLattice(Integer(4), [[Integer(1),Integer(1),Integer(1),Integer(1)]]) Lattice of degree 4 and rank 1 over Integer Ring Basis matrix: [1 1 1 1] Standard scalar product >>> IntegralLattice("A2", [[Integer(1),Integer(1)]]) # needs sage.graphs Lattice of degree 2 and rank 1 over Integer Ring Basis matrix: [1 1] Inner product matrix: [ 2 -1] [-1 2] 
- sage.modules.free_quadratic_module_integer_symmetric.IntegralLatticeDirectSum(Lattices, return_embeddings=False)[source]¶
- Return the direct sum of the lattices contained in the list - Lattices.- INPUT: - Lattices– list of lattices- [L_1,...,L_n]
- return_embeddings– boolean (default:- False)
 - OUTPUT: - The direct sum of the \(L_i\) if - return_embeddingsis- Falseor the tuple- [L, phi]where \(L\) is the direct sum of \(L_i\) and- phiis the list of embeddings from \(L_i\) to \(L\).- EXAMPLES: - sage: # needs sage.graphs sage: from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeDirectSum sage: L1 = IntegralLattice("D4") sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) sage: L3 = IntegralLattice("A4", [[0, 1, 1, 2], [1, 2, 3, 1]]) sage: Lattices = [L1, L2, L3] sage: IntegralLatticeDirectSum([L1, L2, L3]) Lattice of degree 11 and rank 7 over Integer Ring Basis matrix: [1 0 0 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 0 0] [0 0 0 0 1 1 2 0 0 0 0] [0 0 0 0 0 0 0 0 1 1 2] [0 0 0 0 0 0 0 1 2 3 1] Inner product matrix: [ 2 -1 0 0 0 0 0 0 0 0 0] [-1 2 -1 -1 0 0 0 0 0 0 0] [ 0 -1 2 0 0 0 0 0 0 0 0] [ 0 -1 0 2 0 0 0 0 0 0 0] [ 0 0 0 0 2 -1 0 0 0 0 0] [ 0 0 0 0 -1 2 -1 0 0 0 0] [ 0 0 0 0 0 -1 2 0 0 0 0] [ 0 0 0 0 0 0 0 2 -1 0 0] [ 0 0 0 0 0 0 0 -1 2 -1 0] [ 0 0 0 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 0 0 0 -1 2] sage: [L, phi] = IntegralLatticeDirectSum([L1, L2, L3], True) sage: LL3 = L.sublattice(phi[2].image().basis_matrix()) sage: L3.discriminant() == LL3.discriminant() True sage: x = L3([1, 2, 3, 1]) sage: phi[2](x).inner_product(phi[2](x)) == x.inner_product(x) True - >>> from sage.all import * >>> # needs sage.graphs >>> from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeDirectSum >>> L1 = IntegralLattice("D4") >>> L2 = IntegralLattice("A3", [[Integer(1), Integer(1), Integer(2)]]) >>> L3 = IntegralLattice("A4", [[Integer(0), Integer(1), Integer(1), Integer(2)], [Integer(1), Integer(2), Integer(3), Integer(1)]]) >>> Lattices = [L1, L2, L3] >>> IntegralLatticeDirectSum([L1, L2, L3]) Lattice of degree 11 and rank 7 over Integer Ring Basis matrix: [1 0 0 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 0 0] [0 0 0 0 1 1 2 0 0 0 0] [0 0 0 0 0 0 0 0 1 1 2] [0 0 0 0 0 0 0 1 2 3 1] Inner product matrix: [ 2 -1 0 0 0 0 0 0 0 0 0] [-1 2 -1 -1 0 0 0 0 0 0 0] [ 0 -1 2 0 0 0 0 0 0 0 0] [ 0 -1 0 2 0 0 0 0 0 0 0] [ 0 0 0 0 2 -1 0 0 0 0 0] [ 0 0 0 0 -1 2 -1 0 0 0 0] [ 0 0 0 0 0 -1 2 0 0 0 0] [ 0 0 0 0 0 0 0 2 -1 0 0] [ 0 0 0 0 0 0 0 -1 2 -1 0] [ 0 0 0 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 0 0 0 -1 2] >>> [L, phi] = IntegralLatticeDirectSum([L1, L2, L3], True) >>> LL3 = L.sublattice(phi[Integer(2)].image().basis_matrix()) >>> L3.discriminant() == LL3.discriminant() True >>> x = L3([Integer(1), Integer(2), Integer(3), Integer(1)]) >>> phi[Integer(2)](x).inner_product(phi[Integer(2)](x)) == x.inner_product(x) True 
- sage.modules.free_quadratic_module_integer_symmetric.IntegralLatticeGluing(Lattices, glue, return_embeddings=False)[source]¶
- Return an overlattice of the direct sum as defined by - glue.- INPUT: - Lattices– list of lattices \([L_1,...,L_n]\)
- glue– list where the elements are lists in the form \([g_1,...,g_n]\); here \(g_i\) is an element of the discriminant group of \(L_i`and the overlattice is spanned by the additional ``[sum(g) for g in glue]`\)
- return_embeddings– boolean (default:- False)
 - OUTPUT: - The glued lattice given by \(L_i\) and - glueif- return_embeddingsis- Falseor the tuple- [L, phi]where \(L\) is the glued lattice and- phithe list of embeddings from \(L_i\) to \(L\)- EXAMPLES: - A single lattice can be glued. This is the same as taking an overlattice: - sage: from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeGluing sage: L1 = IntegralLattice(matrix([[4]])) sage: g1 = L1.discriminant_group().gens()[0] sage: glue = [[2 * g1]] sage: L = IntegralLatticeGluing([L1], glue) sage: L Lattice of degree 1 and rank 1 over Integer Ring Basis matrix: [1/2] Inner product matrix: [4] sage: L.gram_matrix() [1] sage: IntegralLatticeGluing([L1], glue, return_embeddings=True) [Lattice of degree 1 and rank 1 over Integer Ring Basis matrix: [1/2] Inner product matrix: [4], [Free module morphism defined by the matrix [2] Domain: Lattice of degree 1 and rank 1 over Integer Ring Standard basis Inner product matrix: [4] Codomain: Lattice of degree 1 and rank 1 over Integer Ring Basis matrix: [1/2] Inner product matrix: [4]]] sage: # needs sage.graphs sage: L1 = IntegralLattice([[2]]) sage: L2 = IntegralLattice([[2]]) sage: AL1 = L1.discriminant_group() sage: AL2 = L2.discriminant_group() sage: AL1 Finite quadratic module over Integer Ring with invariants (2,) Gram matrix of the quadratic form with values in Q/2Z: [1/2] sage: g1 = L1.discriminant_group().gens()[0] sage: g2 = L2.discriminant_group().gens()[0] sage: glue = [[g1, g2]] sage: IntegralLatticeGluing([L1, L2], glue) Lattice of degree 2 and rank 2 over Integer Ring Basis matrix: [1/2 1/2] [ 0 1] Inner product matrix: [2 0] [0 2] sage: # needs sage.graphs sage: L1 = IntegralLattice("A4") sage: L2 = IntegralLattice("A4") sage: g1 = L1.discriminant_group().gens()[0] sage: g2 = L2.discriminant_group().gens()[0] sage: glue = [[g1, 2 * g2]] sage: [V, phi] = IntegralLatticeGluing([L1, L2], glue, True) sage: V Lattice of degree 8 and rank 8 over Integer Ring Basis matrix: [1/5 2/5 3/5 4/5 2/5 4/5 1/5 3/5] [ 0 1 0 0 0 0 0 0] [ 0 0 1 0 0 0 0 0] [ 0 0 0 1 0 0 0 0] [ 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 0 1] Inner product matrix: [ 2 -1 0 0 0 0 0 0] [-1 2 -1 0 0 0 0 0] [ 0 -1 2 -1 0 0 0 0] [ 0 0 -1 2 0 0 0 0] [ 0 0 0 0 2 -1 0 0] [ 0 0 0 0 -1 2 -1 0] [ 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 -1 2] sage: V.sublattice(phi[0].image().basis_matrix()) Lattice of degree 8 and rank 4 over Integer Ring Basis matrix: [1 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0] Inner product matrix: [ 2 -1 0 0 0 0 0 0] [-1 2 -1 0 0 0 0 0] [ 0 -1 2 -1 0 0 0 0] [ 0 0 -1 2 0 0 0 0] [ 0 0 0 0 2 -1 0 0] [ 0 0 0 0 -1 2 -1 0] [ 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 -1 2] - >>> from sage.all import * >>> from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeGluing >>> L1 = IntegralLattice(matrix([[Integer(4)]])) >>> g1 = L1.discriminant_group().gens()[Integer(0)] >>> glue = [[Integer(2) * g1]] >>> L = IntegralLatticeGluing([L1], glue) >>> L Lattice of degree 1 and rank 1 over Integer Ring Basis matrix: [1/2] Inner product matrix: [4] >>> L.gram_matrix() [1] >>> IntegralLatticeGluing([L1], glue, return_embeddings=True) [Lattice of degree 1 and rank 1 over Integer Ring Basis matrix: [1/2] Inner product matrix: [4], [Free module morphism defined by the matrix [2] Domain: Lattice of degree 1 and rank 1 over Integer Ring Standard basis Inner product matrix: [4] Codomain: Lattice of degree 1 and rank 1 over Integer Ring Basis matrix: [1/2] Inner product matrix: [4]]] >>> # needs sage.graphs >>> L1 = IntegralLattice([[Integer(2)]]) >>> L2 = IntegralLattice([[Integer(2)]]) >>> AL1 = L1.discriminant_group() >>> AL2 = L2.discriminant_group() >>> AL1 Finite quadratic module over Integer Ring with invariants (2,) Gram matrix of the quadratic form with values in Q/2Z: [1/2] >>> g1 = L1.discriminant_group().gens()[Integer(0)] >>> g2 = L2.discriminant_group().gens()[Integer(0)] >>> glue = [[g1, g2]] >>> IntegralLatticeGluing([L1, L2], glue) Lattice of degree 2 and rank 2 over Integer Ring Basis matrix: [1/2 1/2] [ 0 1] Inner product matrix: [2 0] [0 2] >>> # needs sage.graphs >>> L1 = IntegralLattice("A4") >>> L2 = IntegralLattice("A4") >>> g1 = L1.discriminant_group().gens()[Integer(0)] >>> g2 = L2.discriminant_group().gens()[Integer(0)] >>> glue = [[g1, Integer(2) * g2]] >>> [V, phi] = IntegralLatticeGluing([L1, L2], glue, True) >>> V Lattice of degree 8 and rank 8 over Integer Ring Basis matrix: [1/5 2/5 3/5 4/5 2/5 4/5 1/5 3/5] [ 0 1 0 0 0 0 0 0] [ 0 0 1 0 0 0 0 0] [ 0 0 0 1 0 0 0 0] [ 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 0 1] Inner product matrix: [ 2 -1 0 0 0 0 0 0] [-1 2 -1 0 0 0 0 0] [ 0 -1 2 -1 0 0 0 0] [ 0 0 -1 2 0 0 0 0] [ 0 0 0 0 2 -1 0 0] [ 0 0 0 0 -1 2 -1 0] [ 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 -1 2] >>> V.sublattice(phi[Integer(0)].image().basis_matrix()) Lattice of degree 8 and rank 4 over Integer Ring Basis matrix: [1 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0] Inner product matrix: [ 2 -1 0 0 0 0 0 0] [-1 2 -1 0 0 0 0 0] [ 0 -1 2 -1 0 0 0 0] [ 0 0 -1 2 0 0 0 0] [ 0 0 0 0 2 -1 0 0] [ 0 0 0 0 -1 2 -1 0] [ 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 -1 2] - Different gluings can be composed: - sage: # needs sage.graphs sage: D4 = IntegralLattice("D4") sage: D4.discriminant_group() 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] sage: L2 = IntegralLattice(2 * matrix.identity(2)) sage: L2.discriminant_group() Finite quadratic module over Integer Ring with invariants (2, 2) Gram matrix of the quadratic form with values in Q/2Z: [1/2 0] [ 0 1/2] sage: g1 = D4.discriminant_group().gens()[0] sage: g2 = L2.discriminant_group().gens()[0] + L2.discriminant_group().gens()[1] sage: D6, phi = IntegralLatticeGluing([D4, L2], [[g1, g2]], True) sage: AD6 = D6.discriminant_group() sage: AD6.normal_form() Finite quadratic module over Integer Ring with invariants (2, 2) Gram matrix of the quadratic form with values in Q/2Z: [3/2 0] [ 0 3/2] sage: f1, g1 = AD6.normal_form().gens() sage: f2, g2 = L2.discriminant_group().gens() sage: E8, psi = IntegralLatticeGluing([D6, L2], [[f1, f2], [g1, g2]], True) sage: D4embed = E8.sublattice(psi[0](phi[0].image()).basis_matrix()) sage: x = D4([1, 0, 0, 0]) sage: psi[0](phi[0](x)).inner_product(psi[0](phi[0](x))) == x.inner_product(x) True sage: D4embed Lattice of degree 8 and rank 4 over Integer Ring Basis matrix: [1 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0] Inner product matrix: [ 2 -1 0 0 0 0 0 0] [-1 2 -1 -1 0 0 0 0] [ 0 -1 2 0 0 0 0 0] [ 0 -1 0 2 0 0 0 0] [ 0 0 0 0 2 0 0 0] [ 0 0 0 0 0 2 0 0] [ 0 0 0 0 0 0 2 0] [ 0 0 0 0 0 0 0 2] - >>> from sage.all import * >>> # needs sage.graphs >>> D4 = IntegralLattice("D4") >>> D4.discriminant_group() 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] >>> L2 = IntegralLattice(Integer(2) * matrix.identity(Integer(2))) >>> L2.discriminant_group() Finite quadratic module over Integer Ring with invariants (2, 2) Gram matrix of the quadratic form with values in Q/2Z: [1/2 0] [ 0 1/2] >>> g1 = D4.discriminant_group().gens()[Integer(0)] >>> g2 = L2.discriminant_group().gens()[Integer(0)] + L2.discriminant_group().gens()[Integer(1)] >>> D6, phi = IntegralLatticeGluing([D4, L2], [[g1, g2]], True) >>> AD6 = D6.discriminant_group() >>> AD6.normal_form() Finite quadratic module over Integer Ring with invariants (2, 2) Gram matrix of the quadratic form with values in Q/2Z: [3/2 0] [ 0 3/2] >>> f1, g1 = AD6.normal_form().gens() >>> f2, g2 = L2.discriminant_group().gens() >>> E8, psi = IntegralLatticeGluing([D6, L2], [[f1, f2], [g1, g2]], True) >>> D4embed = E8.sublattice(psi[Integer(0)](phi[Integer(0)].image()).basis_matrix()) >>> x = D4([Integer(1), Integer(0), Integer(0), Integer(0)]) >>> psi[Integer(0)](phi[Integer(0)](x)).inner_product(psi[Integer(0)](phi[Integer(0)](x))) == x.inner_product(x) True >>> D4embed Lattice of degree 8 and rank 4 over Integer Ring Basis matrix: [1 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0] Inner product matrix: [ 2 -1 0 0 0 0 0 0] [-1 2 -1 -1 0 0 0 0] [ 0 -1 2 0 0 0 0 0] [ 0 -1 0 2 0 0 0 0] [ 0 0 0 0 2 0 0 0] [ 0 0 0 0 0 2 0 0] [ 0 0 0 0 0 0 2 0] [ 0 0 0 0 0 0 0 2] - The input may be a list of three or more lattices: - sage: # needs sage.graphs sage: A7 = IntegralLattice("A7") sage: D5 = IntegralLattice("D5") sage: gA7 = A7.discriminant_group().gens()[0] sage: gD5 = D5.discriminant_group().gens()[0] sage: [L, phi] = IntegralLatticeGluing([A7, A7, D5, D5], ....: [[gA7, gA7, gD5, 2 * gD5], ....: [gA7, 7 * gA7, 2 * gD5, gD5]], True) sage: L.determinant() 1 sage: B = phi[0].matrix() sage: B*L.gram_matrix()*B.transpose() == A7.gram_matrix() True - >>> from sage.all import * >>> # needs sage.graphs >>> A7 = IntegralLattice("A7") >>> D5 = IntegralLattice("D5") >>> gA7 = A7.discriminant_group().gens()[Integer(0)] >>> gD5 = D5.discriminant_group().gens()[Integer(0)] >>> [L, phi] = IntegralLatticeGluing([A7, A7, D5, D5], ... [[gA7, gA7, gD5, Integer(2) * gD5], ... [gA7, Integer(7) * gA7, Integer(2) * gD5, gD5]], True) >>> L.determinant() 1 >>> B = phi[Integer(0)].matrix() >>> B*L.gram_matrix()*B.transpose() == A7.gram_matrix() True - The gluing takes place in the direct sum of the respective ambient spaces: - sage: # needs sage.graphs sage: L1 = IntegralLattice("D4", [[1, 1, 0, 0], [0, 1, 1, 0]]) sage: L2 = IntegralLattice("E6", [[0, 2, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1]]) sage: [f1, f2] = L1.discriminant_group().gens() sage: [g1, g2] = L2.discriminant_group().gens() sage: [L, phi] = IntegralLatticeGluing([L1, L2], ....: [[f1, g1], [f2, 2 * g2]], True) sage: phi[0] Free module morphism defined by the matrix [ 2 2 -2 -1] [ 0 2 -1 0] Domain: Lattice of degree 4 and rank 2 over Integer Ring Basis matrix: [1 1 0 0] [0 1 1 0] Inner product matrix: [ 2 -1 0 0] [-1 2 -1 -1] [ 0 -1 2 0] [ 0 -1 0 2] Codomain: Lattice of degree 10 and rank 4 over Integer Ring Basis matrix: [ 1/2 0 -1/2 0 0 1/2 0 0 1/2 1/2] [ 0 1/2 1/2 0 0 1/2 0 0 0 0] [ 0 0 0 0 0 1 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 1] Inner product matrix: [ 2 -1 0 0 0 0 0 0 0 0] [-1 2 -1 -1 0 0 0 0 0 0] [ 0 -1 2 0 0 0 0 0 0 0] [ 0 -1 0 2 0 0 0 0 0 0] [ 0 0 0 0 2 0 -1 0 0 0] [ 0 0 0 0 0 2 0 -1 0 0] [ 0 0 0 0 -1 0 2 -1 0 0] [ 0 0 0 0 0 -1 -1 2 -1 0] [ 0 0 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 0 0 -1 2] sage: B = phi[0].matrix() sage: B * L.gram_matrix() * B.transpose() == L1.gram_matrix() True - >>> from sage.all import * >>> # needs sage.graphs >>> L1 = IntegralLattice("D4", [[Integer(1), Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(1), Integer(1), Integer(0)]]) >>> L2 = IntegralLattice("E6", [[Integer(0), Integer(2), Integer(0), Integer(0), Integer(0), Integer(0)], [Integer(0), Integer(0), Integer(0), Integer(0), Integer(1), Integer(1)]]) >>> [f1, f2] = L1.discriminant_group().gens() >>> [g1, g2] = L2.discriminant_group().gens() >>> [L, phi] = IntegralLatticeGluing([L1, L2], ... [[f1, g1], [f2, Integer(2) * g2]], True) >>> phi[Integer(0)] Free module morphism defined by the matrix [ 2 2 -2 -1] [ 0 2 -1 0] Domain: Lattice of degree 4 and rank 2 over Integer Ring Basis matrix: [1 1 0 0] [0 1 1 0] Inner product matrix: [ 2 -1 0 0] [-1 2 -1 -1] [ 0 -1 2 0] [ 0 -1 0 2] Codomain: Lattice of degree 10 and rank 4 over Integer Ring Basis matrix: [ 1/2 0 -1/2 0 0 1/2 0 0 1/2 1/2] [ 0 1/2 1/2 0 0 1/2 0 0 0 0] [ 0 0 0 0 0 1 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 1] Inner product matrix: [ 2 -1 0 0 0 0 0 0 0 0] [-1 2 -1 -1 0 0 0 0 0 0] [ 0 -1 2 0 0 0 0 0 0 0] [ 0 -1 0 2 0 0 0 0 0 0] [ 0 0 0 0 2 0 -1 0 0 0] [ 0 0 0 0 0 2 0 -1 0 0] [ 0 0 0 0 -1 0 2 -1 0 0] [ 0 0 0 0 0 -1 -1 2 -1 0] [ 0 0 0 0 0 0 0 -1 2 -1] [ 0 0 0 0 0 0 0 0 -1 2] >>> B = phi[Integer(0)].matrix() >>> B * L.gram_matrix() * B.transpose() == L1.gram_matrix() True 
- sage.modules.free_quadratic_module_integer_symmetric.local_modification(M, G, p, check=True)[source]¶
- Return a local modification of \(M\) that matches \(G\) at \(p\). - INPUT: - M– a \(\ZZ_p\)-maximal lattice
- G– the gram matrix of a lattice isomorphic to \(M\) over \(\QQ_p\)
- p– a prime number
 - OUTPUT: - an integral lattice \(M'\) in the ambient space of \(M\) such that \(M\) and \(M'\) are locally equal at all completions except at \(p\) where \(M'\) is locally equivalent to the lattice with gram matrix \(G\) - EXAMPLES: - sage: # needs sage.graphs sage.libs.pari sage: from sage.modules.free_quadratic_module_integer_symmetric import local_modification sage: L = IntegralLattice("A3").twist(15) sage: M = L.maximal_overlattice() sage: for p in prime_divisors(L.determinant()): ....: M = local_modification(M, L.gram_matrix(), p) sage: M.genus() == L.genus() True sage: L = IntegralLattice("D4").twist(3*4) sage: M = L.maximal_overlattice() sage: local_modification(M, L.gram_matrix(), 2) Lattice of degree 4 and rank 4 over Integer Ring Basis matrix: [1/3 0 2/3 2/3] [ 0 1/3 0 2/3] [ 0 0 1 0] [ 0 0 0 1] Inner product matrix: [ 24 -12 0 0] [-12 24 -12 -12] [ 0 -12 24 0] [ 0 -12 0 24] - >>> from sage.all import * >>> # needs sage.graphs sage.libs.pari >>> from sage.modules.free_quadratic_module_integer_symmetric import local_modification >>> L = IntegralLattice("A3").twist(Integer(15)) >>> M = L.maximal_overlattice() >>> for p in prime_divisors(L.determinant()): ... M = local_modification(M, L.gram_matrix(), p) >>> M.genus() == L.genus() True >>> L = IntegralLattice("D4").twist(Integer(3)*Integer(4)) >>> M = L.maximal_overlattice() >>> local_modification(M, L.gram_matrix(), Integer(2)) Lattice of degree 4 and rank 4 over Integer Ring Basis matrix: [1/3 0 2/3 2/3] [ 0 1/3 0 2/3] [ 0 0 1 0] [ 0 0 0 1] Inner product matrix: [ 24 -12 0 0] [-12 24 -12 -12] [ 0 -12 24 0] [ 0 -12 0 24]