def TorsionQuadraticForm(q): r""" 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] 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] TESTS:: sage: TorsionQuadraticForm(matrix.diagonal([3/4,3/8,3/8])) Finite quadratic module over Integer Ring with invariants (4, 8, 8) Gram matrix of the quadratic form with values in Q/2Z: [3/4 0 0] [ 0 3/8 0] [ 0 0 3/8] """ q = matrix(QQ, q) if q.nrows() != q.ncols(): raise ValueError("the input must be a square matrix") if q != q.transpose(): raise ValueError("the input must be a symmetric matrix") Q, d = q._clear_denom() S, U, V = Q.smith_form() D = U * q * V Q = FreeQuadraticModule(ZZ, q.ncols(), inner_product_matrix=d**2 * q) denoms = [D[i, i].denominator() for i in range(D.ncols())] rels = Q.span(diagonal_matrix(ZZ, denoms) * U) return TorsionQuadraticModule((1/d)*Q, (1/d)*rels, modulus=1)
def twist(self, s): r""" 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] This form is defined modulo `3`:: sage: q.twist(3) Finite quadratic module over Integer Ring with invariants (3, 9) Gram matrix of the quadratic form with values in Q/3Z: [ 1 0] [ 0 1/3] The next form is defined modulo `4`:: sage: q.twist(4) Finite quadratic module over Integer Ring with invariants (3, 9) Gram matrix of the quadratic form with values in Q/4Z: [4/3 0] [ 0 4/9] """ s = self.base_ring().fraction_field()(s) n = self.V().degree() inner_product_matrix = s * self.V().inner_product_matrix() ambient = FreeQuadraticModule(self.base_ring(), n, inner_product_matrix) V = ambient.span(self.V().basis()) W = ambient.span(self.W().basis()) return TorsionQuadraticModule(V, W)
def TorsionQuadraticForm(q): r""" 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] 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] """ q = matrix(QQ, q) if q.nrows() != q.ncols(): raise ValueError("the input must be a square matrix") if q != q.transpose(): raise ValueError("the input must be a symmetric matrix") Q, d = q._clear_denom() S, U, V = Q.smith_form() D = U * q * V Q = FreeQuadraticModule(ZZ, q.ncols(), inner_product_matrix=d**2 * q) denoms = [D[i,i].denominator() for i in range(D.ncols())] rels = Q.span(diagonal_matrix(ZZ, denoms) * U) return TorsionQuadraticModule((1/d)*Q, (1/d)*rels)
def twist(self, s): r""" 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] This form is defined modulo `3`:: sage: q.twist(3) Finite quadratic module over Integer Ring with invariants (3, 9) Gram matrix of the quadratic form with values in Q/3Z: [ 1 0] [ 0 1/3] The next form is defined modulo `4`:: sage: q.twist(4) Finite quadratic module over Integer Ring with invariants (3, 9) Gram matrix of the quadratic form with values in Q/4Z: [4/3 0] [ 0 4/9] """ s = self.base_ring().fraction_field()(s) n = self.V().degree() inner_product_matrix = s * self.V().inner_product_matrix() ambient = FreeQuadraticModule(self.base_ring(), n, inner_product_matrix) V = ambient.span(self.V().basis()) W = ambient.span(self.W().basis()) return TorsionQuadraticModule(V, W)