def direct_sum(self, M): r""" 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 Basis matrix: [1 0] [0 1] Inner product matrix: [1 0] [0 1] """ IM = matrix.block_diagonal([self.inner_product_matrix(), M.inner_product_matrix()]) ambient = FreeQuadraticModule(ZZ, self.degree() + M.degree(), IM) smzero = matrix.zero(self.rank(), M.degree()) mszero = matrix.zero(M.rank(), self.degree()) basis = self.basis_matrix().augment(smzero).stack( mszero.augment(M.basis_matrix())) ipm = ambient.inner_product_matrix() return FreeQuadraticModule_integer_symmetric(ambient=ambient, basis=basis, inner_product_matrix=ipm, already_echelonized=False)
def direct_sum(self, M): r""" 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 Basis matrix: [1 0] [0 1] Inner product matrix: [1 0] [0 1] """ IM = matrix.block_diagonal( [self.inner_product_matrix(), M.inner_product_matrix()]) ambient = FreeQuadraticModule(ZZ, self.degree() + M.degree(), IM) smzero = matrix.zero(self.rank(), M.degree()) mszero = matrix.zero(M.rank(), self.degree()) basis = self.basis_matrix().augment(smzero).stack( mszero.augment(M.basis_matrix())) ipm = ambient.inner_product_matrix() return FreeQuadraticModule_integer_symmetric(ambient=ambient, basis=basis, inner_product_matrix=ipm, already_echelonized=False)
def gram_matrix_quadratic(self): r""" 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: 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] """ gens = self.gens() n = len(gens) Q = self.base_ring().fraction_field() G = matrix.zero(Q, n) for i in range(n): for j in range(i): G[i, j] = G[j, i] = (gens[i] * gens[j]).lift() G[i, i] = gens[i].q().lift() return G
def gram_matrix_bilinear(self): r""" 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: 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] """ gens = self.gens() n = len(gens) Q = self.base_ring().fraction_field() G = matrix.zero(Q, n) for i in range(n): for j in range(i + 1): G[i, j] = G[j, i] = (gens[i] * gens[j]).lift() return G
def gram_matrix_quadratic(self): r""" 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: 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] """ gens = self._gens n = len(gens) Q = self.base_ring().fraction_field() G = matrix.zero(Q, n) for i in range(n): for j in range(i): G[i,j] = G[j,i] = (gens[i] * gens[j]).lift() G[i,i] = gens[i].q().lift() return G
def gram_matrix_bilinear(self): r""" 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: 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] """ gens = self._gens n = len(gens) Q = self.base_ring().fraction_field() G = matrix.zero(Q, n) for i in range(n): for j in range(i+1): G[i,j] = G[j,i] = (gens[i] * gens[j]).lift() return G
def compacte_liste(listP, FractionField): """ Take a list of rational fractions and return the an equivalent list with minimal degrees. """ check = matrix.zero(ZZ, len(listP)) Res = [P for P in listP] for i, P in enumerate(listP): P = FractionField(P) Q, [case, ind] = replace_p(P, listP, FractionField) check[i, i] = 1 if case != 0: check2 = check check2[i, ind] = case if check2.rank() < check.rank( ): #On vérifie qu'on n'oublie pas une équation! Q = P else: check = check2 if not (Q in Res): Res.remove(P) if Q.numerator().degree() + Q.denominator().degree() == 0: #(in case we had to proportional equations pass else: Res += [Q] return Res
def zero(self): """ Construct the zero morphism of ``self``. EXAMPLES:: sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: H.zero() Morphism from Finite-dimensional algebra of degree 1 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field given by matrix [0 0] """ from sage.matrix.constructor import matrix return FiniteDimensionalAlgebraMorphism( self, matrix.zero(self.domain().ngens(), self.codomain().ngens()), False, False)
def zero(self): """ Construct the zero morphism of ``self``. EXAMPLES:: sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: H.zero() Morphism from Finite-dimensional algebra of degree 1 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field given by matrix [0 0] """ from sage.matrix.constructor import matrix return FiniteDimensionalAlgebraMorphism(self, matrix.zero(self.domain().ngens(), self.codomain().ngens()), False, False)
def IntegralLatticeDirectSum(Lattices, return_embeddings=False): r""" Return the direct sum of the lattices contained in the list ``Lattices``. INPUT: - ``Lattices`` -- a list of lattices ``[L_1,...,L_n]`` - ``return_embeddings`` -- (default: ``False``) a boolean OUTPUT: The direct sum of the `L_i` if ``return_embeddings`` is ``False`` or the tuple ``[L, phi]`` where `L` is the direct sum of `L_i` and ``phi`` is the list of embeddings from `L_i` to `L`. EXAMPLES:: 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 TESTS:: sage: IntegralLatticeDirectSum([IntegralLattice("D4")]) Lattice of degree 4 and rank 4 over Integer Ring Basis matrix: [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] Inner product matrix: [ 2 -1 0 0] [-1 2 -1 -1] [ 0 -1 2 0] [ 0 -1 0 2] sage: L1 = IntegralLattice(2 * matrix.identity(2), [[1/2, 1/2]]) sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) sage: [L, phi] = IntegralLatticeDirectSum([L1, L2], True) sage: L Lattice of degree 5 and rank 2 over Integer Ring Basis matrix: [1/2 1/2 0 0 0] [ 0 0 1 1 2] Inner product matrix: [ 2 0 0 0 0] [ 0 2 0 0 0] [ 0 0 2 -1 0] [ 0 0 -1 2 -1] [ 0 0 0 -1 2] """ for L in Lattices: if not isinstance(L, FreeQuadraticModule_integer_symmetric): raise ValueError("Lattices must be a list of lattices") N = len(Lattices) dims = [L_i.dimension() for L_i in Lattices] degrees = [L_i.degree() for L_i in Lattices] degree_tot = sum(degrees) sum_degree = [sum(degrees[:i]) for i in range(N + 1)] inner_product_list = [copy(L_i.inner_product_matrix()) for L_i in Lattices] IM = matrix.block_diagonal(inner_product_list) ambient = FreeQuadraticModule(ZZ, degree_tot, inner_product_matrix=IM) basis = [ matrix.block(1, 3, [ matrix.zero(dims[i], sum_degree[i]), Lattices[i].basis_matrix(), matrix.zero(dims[i], sum_degree[-1] - sum_degree[i + 1]) ]) for i in range(N) ] basis_matrix = matrix.block(N, 1, basis) ipm = ambient.inner_product_matrix() direct_sum = FreeQuadraticModule_integer_symmetric( ambient=ambient, basis=basis_matrix, inner_product_matrix=ipm, already_echelonized=False) if not return_embeddings: return direct_sum sum_dims = [sum(dims[:i]) for i in range(N + 1)] phi = [ Lattices[i].hom(direct_sum.basis()[sum_dims[i]:sum_dims[i + 1]]) for i in range(N) ] return [direct_sum, phi]
def IntegralLatticeDirectSum(Lattices, return_embeddings=False): r""" Return the direct sum of the lattices contained in the list ``Lattices``. INPUT: - ``Lattices`` -- a list of lattices ``[L_1,...,L_n]`` - ``return_embeddings`` -- (default: ``False``) a boolean OUTPUT: The direct sum of the `L_i` if ``return_embeddings`` is ``False`` or the tuple ``[L, phi]`` where `L` is the direct sum of `L_i` and ``phi`` is the list of embeddings from `L_i` to `L`. EXAMPLES:: 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 TESTS:: sage: IntegralLatticeDirectSum([IntegralLattice("D4")]) Lattice of degree 4 and rank 4 over Integer Ring Basis matrix: [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] Inner product matrix: [ 2 -1 0 0] [-1 2 -1 -1] [ 0 -1 2 0] [ 0 -1 0 2] sage: L1 = IntegralLattice(2 * matrix.identity(2), [[1/2, 1/2]]) sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) sage: [L, phi] = IntegralLatticeDirectSum([L1, L2], True) sage: L Lattice of degree 5 and rank 2 over Integer Ring Basis matrix: [1/2 1/2 0 0 0] [ 0 0 1 1 2] Inner product matrix: [ 2 0 0 0 0] [ 0 2 0 0 0] [ 0 0 2 -1 0] [ 0 0 -1 2 -1] [ 0 0 0 -1 2] """ for L in Lattices: if not isinstance(L, FreeQuadraticModule_integer_symmetric): raise ValueError("Lattices must be a list of lattices") N = len(Lattices) dims = [L_i.dimension() for L_i in Lattices] degrees = [L_i.degree() for L_i in Lattices] dim_tot = sum(dims) degree_tot = sum(degrees) sum_degree = [sum(degrees[:i]) for i in range(N+1)] inner_product_list = [copy(L_i.inner_product_matrix()) for L_i in Lattices] IM = matrix.block_diagonal(inner_product_list) ambient = FreeQuadraticModule(ZZ, degree_tot, inner_product_matrix=IM) basis = [matrix.block(1, 3, [matrix.zero(dims[i], sum_degree[i]), Lattices[i].basis_matrix(), matrix.zero(dims[i], sum_degree[-1] - sum_degree[i+1]) ]) for i in range(N)] basis_matrix = matrix.block(N, 1, basis) ipm = ambient.inner_product_matrix() direct_sum = FreeQuadraticModule_integer_symmetric(ambient=ambient, basis=basis_matrix, inner_product_matrix=ipm, already_echelonized=False) if not return_embeddings: return direct_sum sum_dims = [sum(dims[:i]) for i in range(N+1)] phi = [Lattices[i].hom(direct_sum.basis()[sum_dims[i]:sum_dims[i+1]]) for i in range(N)] return [direct_sum, phi]