Quadratic forms overview¶
AUTHORS:
Jon Hanke (2007-06-19)
Anna Haensch (2010-07-01): Formatting and ReSTification
Simon Brandhorst (2019-10-15):
quadratic_form_from_invariants()
- sage.quadratic_forms.quadratic_form.DiagonalQuadraticForm(R, diag)[source]¶
Return a quadratic form over \(R\) which is a sum of squares.
INPUT:
R
– ringdiag
– list/tuple of elements coercible to \(R\)
OUTPUT: quadratic form
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]); Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 3 0 0 ] [ * * 5 0 ] [ * * * 7 ]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]); Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 3 0 0 ] [ * * 5 0 ] [ * * * 7 ]
- class sage.quadratic_forms.quadratic_form.QuadraticForm(R, n=None, entries=None, unsafe_initialization=False, number_of_automorphisms=None, determinant=None)[source]¶
Bases:
SageObject
The
QuadraticForm
class represents a quadratic form in \(n\) variables with coefficients in the ring \(R\).INPUT:
The constructor may be called in any of the following ways.
QuadraticForm(R, n, entries)
, whereR
– ring for which the quadratic form is definedn
– integer \(\geq 0\)entries
– list of \(n(n+1)/2\) coefficients of the quadratic form in \(R\) (given lexicographically, or equivalently, by rows of the matrix)
QuadraticForm(p)
, wherep
– a homogeneous polynomial of degree \(2\)
QuadraticForm(R, n)
, whereR
– a ringn
– a symmetric \(n \times n\) matrix with even diagonal (relative to \(R\))
QuadraticForm(R)
, whereR
– a symmetric \(n \times n\) matrix with even diagonal (relative to its base ring)
If the keyword argument
unsafe_initialize
is True, then the subsequent fields may by used to force the external initialization of various fields of the quadratic form. Currently the only fields which can be set are:number_of_automorphisms
determinant
OUTPUT: quadratic form
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1,2,3,4,5,6]); Q Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5),Integer(6)]); Q Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ]
sage: Q = QuadraticForm(QQ, 3, [1,2,3,4/3,5,6]); Q Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 3 ] [ * 4/3 5 ] [ * * 6 ] sage: Q[0,0] 1 sage: Q[0,0].parent() Rational Field
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(3), [Integer(1),Integer(2),Integer(3),Integer(4)/Integer(3),Integer(5),Integer(6)]); Q Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 3 ] [ * 4/3 5 ] [ * * 6 ] >>> Q[Integer(0),Integer(0)] 1 >>> Q[Integer(0),Integer(0)].parent() Rational Field
sage: Q = QuadraticForm(QQ, 7, range(28)); Q Quadratic form in 7 variables over Rational Field with coefficients: [ 0 1 2 3 4 5 6 ] [ * 7 8 9 10 11 12 ] [ * * 13 14 15 16 17 ] [ * * * 18 19 20 21 ] [ * * * * 22 23 24 ] [ * * * * * 25 26 ] [ * * * * * * 27 ]
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(7), range(Integer(28))); Q Quadratic form in 7 variables over Rational Field with coefficients: [ 0 1 2 3 4 5 6 ] [ * 7 8 9 10 11 12 ] [ * * 13 14 15 16 17 ] [ * * * 18 19 20 21 ] [ * * * * 22 23 24 ] [ * * * * * 25 26 ] [ * * * * * * 27 ]
sage: Q = QuadraticForm(QQ, 2, range(1,4)) sage: A = Matrix(ZZ, 2, 2, [-1,0,0,1]) sage: Q(A) Quadratic form in 2 variables over Rational Field with coefficients: [ 1 -2 ] [ * 3 ]
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(2), range(Integer(1),Integer(4))) >>> A = Matrix(ZZ, Integer(2), Integer(2), [-Integer(1),Integer(0),Integer(0),Integer(1)]) >>> Q(A) Quadratic form in 2 variables over Rational Field with coefficients: [ 1 -2 ] [ * 3 ]
sage: m = matrix(2, 2, [1,2,3,4]) sage: m + m.transpose() [2 5] [5 8] sage: QuadraticForm(m + m.transpose()) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 5 ] [ * 4 ]
>>> from sage.all import * >>> m = matrix(Integer(2), Integer(2), [Integer(1),Integer(2),Integer(3),Integer(4)]) >>> m + m.transpose() [2 5] [5 8] >>> QuadraticForm(m + m.transpose()) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 5 ] [ * 4 ]
sage: P.<x,y,z> = QQ[] sage: p = x^2 + 2*x*y + x*z/2 + y^2 + y*z/3 sage: QuadraticForm(p) Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 1/2 ] [ * 1 1/3 ] [ * * 0 ]
>>> from sage.all import * >>> P = QQ['x, y, z']; (x, y, z,) = P._first_ngens(3) >>> p = x**Integer(2) + Integer(2)*x*y + x*z/Integer(2) + y**Integer(2) + y*z/Integer(3) >>> QuadraticForm(p) Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 1/2 ] [ * 1 1/3 ] [ * * 0 ]
sage: QuadraticForm(ZZ, m + m.transpose()) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 5 ] [ * 4 ]
>>> from sage.all import * >>> QuadraticForm(ZZ, m + m.transpose()) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 5 ] [ * 4 ]
sage: QuadraticForm(QQ, m + m.transpose()) Quadratic form in 2 variables over Rational Field with coefficients: [ 1 5 ] [ * 4 ]
>>> from sage.all import * >>> QuadraticForm(QQ, m + m.transpose()) Quadratic form in 2 variables over Rational Field with coefficients: [ 1 5 ] [ * 4 ]
- CS_genus_symbol_list(force_recomputation=False)[source]¶
Return the list of Conway-Sloane genus symbols in increasing order of primes dividing 2*det.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3,4]) sage: Q.CS_genus_symbol_list() [Genus symbol at 2: [2^-2 4^1 8^1]_6, Genus symbol at 3: 1^3 3^-1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3),Integer(4)]) >>> Q.CS_genus_symbol_list() [Genus symbol at 2: [2^-2 4^1 8^1]_6, Genus symbol at 3: 1^3 3^-1]
- GHY_mass__maximal()[source]¶
Use the GHY formula to compute the mass of a (maximal?) quadratic lattice. This works for any number field.
REFERENCES:
See [GHY, Prop 7.4 and 7.5, p121] and [GY, Thrm 10.20, p25].
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.GHY_mass__maximal()
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.GHY_mass__maximal()
- Gram_det()[source]¶
Return the determinant of the Gram matrix of \(Q\).
Note
This is defined over the fraction field of the ring of the quadratic form, but is often not defined over the same ring as the quadratic form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.Gram_det() 2
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.Gram_det() 2
- Gram_matrix()[source]¶
Return a (symmetric) Gram matrix \(A\) for the quadratic form \(Q\), meaning that
\[Q(x) = x^t\cdot A\cdot x,\]defined over the base ring of \(Q\). If this is not possible, then a
TypeError
is raised.EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: A = Q.Gram_matrix(); A [1 0 0 0] [0 3 0 0] [0 0 5 0] [0 0 0 7] sage: A.base_ring() Integer Ring
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> A = Q.Gram_matrix(); A [1 0 0 0] [0 3 0 0] [0 0 5 0] [0 0 0 7] >>> A.base_ring() Integer Ring
- Gram_matrix_rational()[source]¶
Return a (symmetric) Gram matrix \(A\) for the quadratic form \(Q\), meaning that
\[Q(x) = x^t\cdot A\cdot x,\]defined over the fraction field of the base ring.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: A = Q.Gram_matrix_rational(); A [1 0 0 0] [0 3 0 0] [0 0 5 0] [0 0 0 7] sage: A.base_ring() Rational Field
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> A = Q.Gram_matrix_rational(); A [1 0 0 0] [0 3 0 0] [0 0 5 0] [0 0 0 7] >>> A.base_ring() Rational Field
- Hessian_matrix()[source]¶
Return the Hessian matrix \(A\) for which \(Q(X) = (1/2) X^t\cdot A\cdot X\).
EXAMPLES:
sage: Q = QuadraticForm(QQ, 2, range(1,4)); Q Quadratic form in 2 variables over Rational Field with coefficients: [ 1 2 ] [ * 3 ] sage: Q.Hessian_matrix() [2 2] [2 6] sage: Q.matrix().base_ring() Rational Field
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(2), range(Integer(1),Integer(4))); Q Quadratic form in 2 variables over Rational Field with coefficients: [ 1 2 ] [ * 3 ] >>> Q.Hessian_matrix() [2 2] [2 6] >>> Q.matrix().base_ring() Rational Field
- Kitaoka_mass_at_2()[source]¶
Return the local mass of the quadratic form when \(p=2\), according to Theorem 5.6.3 on pp108–9 of Kitaoka’s Book “The Arithmetic of Quadratic Forms”.
OUTPUT: a rational number > 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.Kitaoka_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! 1/2
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.Kitaoka_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! 1/2
- Pall_mass_density_at_odd_prime(p)[source]¶
Return the local representation density of a form (for representing itself) defined over \(\ZZ\), at some prime \(p>2\).
REFERENCES:
Pall’s article “The Weight of a Genus of Positive n-ary Quadratic Forms” appearing in Proc. Symp. Pure Math. VIII (1965), pp95–105.
INPUT:
p
– a prime number > 2
OUTPUT: a rational number
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1,0,0,1,0,1]) sage: Q.Pall_mass_density_at_odd_prime(3) [(0, Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 0 ] [ * 1 0 ] [ * * 1 ])] [(0, 3, 8)] [8/9] 8/9 8/9
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1),Integer(0),Integer(0),Integer(1),Integer(0),Integer(1)]) >>> Q.Pall_mass_density_at_odd_prime(Integer(3)) [(0, Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 0 ] [ * 1 0 ] [ * * 1 ])] [(0, 3, 8)] [8/9] 8/9 8/9
- Watson_mass_at_2()[source]¶
Return the local mass of the quadratic form when \(p=2\), according to Watson’s Theorem 1 of “The 2-adic density of a quadratic form” in Mathematika 23 (1976), pp 94–106.
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.Watson_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! # needs sage.symbolic 384
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.Watson_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! # needs sage.symbolic 384
- add_symmetric(c, i, j, in_place=False)[source]¶
Perform the substitution \(x_j \longmapsto x_j + c\cdot x_i\), which has the effect (on associated matrices) of symmetrically adding \(c\) times the \(j\)-th row/column to the \(i\)-th row/column.
NOTE: This is meant for compatibility with previous code, which implemented a matrix model for this class. It is used in the method
local_normal_form()
.INPUT:
c
– an element ofself.base_ring()
i
,j
– integers \(\geq 0\)
OUTPUT:
a
QuadraticForm
(by default, otherwise none)EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, range(1,7)); Q Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ] sage: Q.add_symmetric(-1, 1, 0) Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 3 ] [ * 3 2 ] [ * * 6 ] sage: Q.add_symmetric(-3/2, 2, 0) # ERROR: -3/2 isn't in the base ring ZZ Traceback (most recent call last): ... RuntimeError: this coefficient cannot be coerced to an element of the base ring for the quadratic form
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), range(Integer(1),Integer(7))); Q Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ] >>> Q.add_symmetric(-Integer(1), Integer(1), Integer(0)) Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 3 ] [ * 3 2 ] [ * * 6 ] >>> Q.add_symmetric(-Integer(3)/Integer(2), Integer(2), Integer(0)) # ERROR: -3/2 isn't in the base ring ZZ Traceback (most recent call last): ... RuntimeError: this coefficient cannot be coerced to an element of the base ring for the quadratic form
sage: Q = QuadraticForm(QQ, 3, range(1,7)); Q Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ] sage: Q.add_symmetric(-3/2, 2, 0) Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 0 ] [ * 4 2 ] [ * * 15/4 ]
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(3), range(Integer(1),Integer(7))); Q Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ] >>> Q.add_symmetric(-Integer(3)/Integer(2), Integer(2), Integer(0)) Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 0 ] [ * 4 2 ] [ * * 15/4 ]
- adjoint()[source]¶
This gives the adjoint (integral) quadratic form associated to the given form, essentially defined by taking the adjoint of the matrix.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,5]) sage: Q.adjoint() Quadratic form in 2 variables over Integer Ring with coefficients: [ 5 -2 ] [ * 1 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(5)]) >>> Q.adjoint() Quadratic form in 2 variables over Integer Ring with coefficients: [ 5 -2 ] [ * 1 ]
sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.adjoint() Quadratic form in 3 variables over Integer Ring with coefficients: [ 39 2 8 ] [ * 19 4 ] [ * * 8 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q.adjoint() Quadratic form in 3 variables over Integer Ring with coefficients: [ 39 2 8 ] [ * 19 4 ] [ * * 8 ]
- adjoint_primitive()[source]¶
Return the primitive adjoint of the quadratic form, which is the smallest discriminant integer-valued quadratic form whose matrix is a scalar multiple of the inverse of the matrix of the given quadratic form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.adjoint_primitive() Quadratic form in 2 variables over Integer Ring with coefficients: [ 3 -2 ] [ * 1 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.adjoint_primitive() Quadratic form in 2 variables over Integer Ring with coefficients: [ 3 -2 ] [ * 1 ]
- anisotropic_primes()[source]¶
Return a list with all of the anisotropic primes of the quadratic form.
The infinite place is denoted by \(-1\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.anisotropic_primes() # needs sage.libs.pari [2, -1] sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.anisotropic_primes() # needs sage.libs.pari [2, -1] sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1]) sage: Q.anisotropic_primes() # needs sage.libs.pari [-1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.anisotropic_primes() # needs sage.libs.pari [2, -1] >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.anisotropic_primes() # needs sage.libs.pari [2, -1] >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.anisotropic_primes() # needs sage.libs.pari [-1]
- antiadjoint()[source]¶
This gives an (integral) form such that its adjoint is the given form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.adjoint().antiadjoint() Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 -1 ] [ * 2 -1 ] [ * * 5 ] sage: Q.antiadjoint() # needs sage.symbolic Traceback (most recent call last): ... ValueError: not an adjoint
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q.adjoint().antiadjoint() Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 -1 ] [ * 2 -1 ] [ * * 5 ] >>> Q.antiadjoint() # needs sage.symbolic Traceback (most recent call last): ... ValueError: not an adjoint
- automorphism_group()[source]¶
Return the group of automorphisms of the quadratic form.
OUTPUT: a
MatrixGroup
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.automorphism_group() Matrix group over Rational Field with 3 generators ( [ 0 0 1] [1 0 0] [ 1 0 0] [-1 0 0] [0 0 1] [ 0 -1 0] [ 0 1 0], [0 1 0], [ 0 0 1] )
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.automorphism_group() Matrix group over Rational Field with 3 generators ( [ 0 0 1] [1 0 0] [ 1 0 0] [-1 0 0] [0 0 1] [ 0 -1 0] [ 0 1 0], [0 1 0], [ 0 0 1] )
sage: DiagonalQuadraticForm(ZZ, [1,3,5,7]).automorphism_group() Matrix group over Rational Field with 4 generators ( [-1 0 0 0] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0] [ 0 -1 0 0] [ 0 -1 0 0] [ 0 1 0 0] [ 0 1 0 0] [ 0 0 -1 0] [ 0 0 1 0] [ 0 0 -1 0] [ 0 0 1 0] [ 0 0 0 -1], [ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 -1] )
>>> from sage.all import * >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]).automorphism_group() Matrix group over Rational Field with 4 generators ( [-1 0 0 0] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0] [ 0 -1 0 0] [ 0 -1 0 0] [ 0 1 0 0] [ 0 1 0 0] [ 0 0 -1 0] [ 0 0 1 0] [ 0 0 -1 0] [ 0 0 1 0] [ 0 0 0 -1], [ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 -1] )
The smallest possible automorphism group has order two, since we can always change all signs:
sage: Q = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3]) sage: Q.automorphism_group() Matrix group over Rational Field with 1 generators ( [-1 0 0] [ 0 -1 0] [ 0 0 -1] )
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(2), Integer(1), Integer(2), Integer(2), Integer(1), Integer(3)]) >>> Q.automorphism_group() Matrix group over Rational Field with 1 generators ( [-1 0 0] [ 0 -1 0] [ 0 0 -1] )
- automorphisms()[source]¶
Return the list of the automorphisms of the quadratic form.
OUTPUT: list of matrices
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.number_of_automorphisms() 48 sage: 2^3 * factorial(3) 48 sage: len(Q.automorphisms()) # needs sage.libs.gap 48
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.number_of_automorphisms() 48 >>> Integer(2)**Integer(3) * factorial(Integer(3)) 48 >>> len(Q.automorphisms()) # needs sage.libs.gap 48
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.number_of_automorphisms() 16 sage: aut = Q.automorphisms() # needs sage.libs.gap sage: len(aut) # needs sage.libs.gap 16 sage: all(Q(M) == Q for M in aut) # needs sage.libs.gap True sage: Q = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3]) sage: sorted(Q.automorphisms()) # needs sage.libs.gap [ [-1 0 0] [1 0 0] [ 0 -1 0] [0 1 0] [ 0 0 -1], [0 0 1] ]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.number_of_automorphisms() 16 >>> aut = Q.automorphisms() # needs sage.libs.gap >>> len(aut) # needs sage.libs.gap 16 >>> all(Q(M) == Q for M in aut) # needs sage.libs.gap True >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(2), Integer(1), Integer(2), Integer(2), Integer(1), Integer(3)]) >>> sorted(Q.automorphisms()) # needs sage.libs.gap [ [-1 0 0] [1 0 0] [ 0 -1 0] [0 1 0] [ 0 0 -1], [0 0 1] ]
- base_change_to(*args, **kwds)[source]¶
Deprecated: Use
change_ring()
instead. See Issue #35248 for details.
- base_ring()[source]¶
Return the ring over which the quadratic form is defined.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.base_ring() Integer Ring
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.base_ring() Integer Ring
- basiclemma(M)[source]¶
Find a number represented by
self
and coprime to \(M\).EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [2, 1, 3]) sage: Q.basiclemma(6) 71
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(2), Integer(1), Integer(3)]) >>> Q.basiclemma(Integer(6)) 71
- basiclemmavec(M)[source]¶
Find a vector where the value of the quadratic form is coprime to \(M\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [2, 1, 5]) sage: Q.basiclemmavec(10) (6, 5) sage: Q(_) 227
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(2), Integer(1), Integer(5)]) >>> Q.basiclemmavec(Integer(10)) (6, 5) >>> Q(_) 227
- basis_of_short_vectors(show_lengths=False)[source]¶
Return a basis for \(\ZZ^n\) made of vectors with minimal lengths \(Q(v)\).
OUTPUT: a tuple of vectors, and optionally a tuple of values for each vector
This uses pari:qfminim.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.basis_of_short_vectors() ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) sage: Q.basis_of_short_vectors(True) (((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), (1, 3, 5, 7))
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.basis_of_short_vectors() ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) >>> Q.basis_of_short_vectors(True) (((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), (1, 3, 5, 7))
The returned vectors are immutable:
sage: v = Q.basis_of_short_vectors()[0] sage: v (1, 0, 0, 0) sage: v[0] = 0 Traceback (most recent call last): ... ValueError: vector is immutable; please change a copy instead (use copy())
>>> from sage.all import * >>> v = Q.basis_of_short_vectors()[Integer(0)] >>> v (1, 0, 0, 0) >>> v[Integer(0)] = Integer(0) Traceback (most recent call last): ... ValueError: vector is immutable; please change a copy instead (use copy())
- bilinear_map(v, w)[source]¶
Return the value of the associated bilinear map on two vectors.
Given a quadratic form \(Q\) over some base ring \(R\) with characteristic not equal to 2, this gives the image of two vectors with coefficients in \(R\) under the associated bilinear map \(B\), given by the relation \(2 B(v,w) = Q(v) + Q(w) - Q(v+w)\).
INPUT:
v
,w
– two vectors
OUTPUT: an element of the base ring \(R\)
EXAMPLES:
First, an example over \(\ZZ\):
sage: Q = QuadraticForm(ZZ, 3, [1,4,0,1,4,1]) sage: v = vector(ZZ, (1,2,0)) sage: w = vector(ZZ, (0,1,1)) sage: Q.bilinear_map(v, w) 8
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1),Integer(4),Integer(0),Integer(1),Integer(4),Integer(1)]) >>> v = vector(ZZ, (Integer(1),Integer(2),Integer(0))) >>> w = vector(ZZ, (Integer(0),Integer(1),Integer(1))) >>> Q.bilinear_map(v, w) 8
This also works over \(\QQ\):
sage: Q = QuadraticForm(QQ, 2, [1/2,2,1]) sage: v = vector(QQ, (1,1)) sage: w = vector(QQ, (1/2,2)) sage: Q.bilinear_map(v, w) 19/4
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(2), [Integer(1)/Integer(2),Integer(2),Integer(1)]) >>> v = vector(QQ, (Integer(1),Integer(1))) >>> w = vector(QQ, (Integer(1)/Integer(2),Integer(2))) >>> Q.bilinear_map(v, w) 19/4
The vectors must have the correct length:
sage: Q = DiagonalQuadraticForm(ZZ, [1,7,7]) sage: v = vector((1,2)) sage: w = vector((1,1,1)) sage: Q.bilinear_map(v, w) Traceback (most recent call last): ... TypeError: vectors must have length 3
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(7),Integer(7)]) >>> v = vector((Integer(1),Integer(2))) >>> w = vector((Integer(1),Integer(1),Integer(1))) >>> Q.bilinear_map(v, w) Traceback (most recent call last): ... TypeError: vectors must have length 3
This does not work if the characteristic is 2:
sage: # needs sage.rings.finite_rings sage: Q = DiagonalQuadraticForm(GF(2), [1,1,1]) sage: v = vector((1,1,1)) sage: w = vector((1,1,1)) sage: Q.bilinear_map(v, w) Traceback (most recent call last): ... TypeError: not defined for rings of characteristic 2
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> Q = DiagonalQuadraticForm(GF(Integer(2)), [Integer(1),Integer(1),Integer(1)]) >>> v = vector((Integer(1),Integer(1),Integer(1))) >>> w = vector((Integer(1),Integer(1),Integer(1))) >>> Q.bilinear_map(v, w) Traceback (most recent call last): ... TypeError: not defined for rings of characteristic 2
- change_ring(R)[source]¶
Alters the quadratic form to have all coefficients defined over the new base ring \(R\). Here \(R\) must be coercible to from the current base ring.
Note
This is preferable to performing an explicit coercion through the
base_ring()
method, which does not affect the individual coefficients. This is particularly useful for performing fast modular arithmetic evaluations.INPUT:
R
– a ring
OUTPUT: quadratic form
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1]); Q Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 1 ] sage: Q1 = Q.change_ring(IntegerModRing(5)); Q1 Quadratic form in 2 variables over Ring of integers modulo 5 with coefficients: [ 1 0 ] [ * 1 ] sage: Q1([35,11]) 1
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]); Q Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 1 ] >>> Q1 = Q.change_ring(IntegerModRing(Integer(5))); Q1 Quadratic form in 2 variables over Ring of integers modulo 5 with coefficients: [ 1 0 ] [ * 1 ] >>> Q1([Integer(35),Integer(11)]) 1
- cholesky_decomposition(bit_prec=53)[source]¶
Give the Cholesky decomposition of this quadratic form \(Q\) as a real matrix of precision
bit_prec
.RESTRICTIONS:
\(Q\) must be given as a
QuadraticForm
defined over \(\ZZ\), \(\QQ\), or some real field. If it is over some real field, then an error is raised if the precision given is not less than the defined precision of the real field defining the quadratic form!REFERENCE:
Cohen’s “A Course in Computational Algebraic Number Theory” book, p 103.
INPUT:
bit_prec
– a natural number (default: 53)
OUTPUT: an upper triangular real matrix of precision
bit_prec
Todo
If we only care about working over the real double field (
RDF
), then we can use the methodcholesky()
present for square matrices over that.Note
There is a note in the original code reading
Finds the Cholesky decomposition of a quadratic form -- as an upper-triangular matrix! (It's assumed to be global, hence twice the form it refers to.) <-- Python revision asks: Is this true?!? =|
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.cholesky_decomposition() [ 1.00000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 1.00000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 1.00000000000000]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.cholesky_decomposition() [ 1.00000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 1.00000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 1.00000000000000]
sage: Q = QuadraticForm(QQ, 3, range(1,7)); Q Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ] sage: Q.cholesky_decomposition() [ 1.00000000000000 1.00000000000000 1.50000000000000] [0.000000000000000 3.00000000000000 0.333333333333333] [0.000000000000000 0.000000000000000 3.41666666666667]
>>> from sage.all import * >>> Q = QuadraticForm(QQ, Integer(3), range(Integer(1),Integer(7))); Q Quadratic form in 3 variables over Rational Field with coefficients: [ 1 2 3 ] [ * 4 5 ] [ * * 6 ] >>> Q.cholesky_decomposition() [ 1.00000000000000 1.00000000000000 1.50000000000000] [0.000000000000000 3.00000000000000 0.333333333333333] [0.000000000000000 0.000000000000000 3.41666666666667]
- clifford_conductor()[source]¶
Return the product of all primes where the Clifford invariant is \(-1\).
Note
For ternary forms, this is the discriminant of the quaternion algebra associated to the quadratic space (i.e. the even Clifford algebra).
EXAMPLES:
sage: # needs sage.libs.pari sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.clifford_invariant(2) 1 sage: Q.clifford_invariant(37) -1 sage: Q.clifford_conductor() 37 sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).clifford_conductor() # needs sage.libs.pari 2 sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor() # needs sage.libs.pari 30
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q.clifford_invariant(Integer(2)) 1 >>> Q.clifford_invariant(Integer(37)) -1 >>> Q.clifford_conductor() 37 >>> DiagonalQuadraticForm(ZZ, [Integer(1), Integer(1), Integer(1)]).clifford_conductor() # needs sage.libs.pari 2 >>> QuadraticForm(ZZ, Integer(3), [Integer(2), -Integer(2), Integer(0), Integer(2), Integer(0), Integer(5)]).clifford_conductor() # needs sage.libs.pari 30
For hyperbolic spaces, the Clifford conductor is 1:
sage: # needs sage.libs.pari sage: H = QuadraticForm(ZZ, 2, [0, 1, 0]) sage: H.clifford_conductor() 1 sage: (H + H).clifford_conductor() 1 sage: (H + H + H).clifford_conductor() 1 sage: (H + H + H + H).clifford_conductor() 1
>>> from sage.all import * >>> # needs sage.libs.pari >>> H = QuadraticForm(ZZ, Integer(2), [Integer(0), Integer(1), Integer(0)]) >>> H.clifford_conductor() 1 >>> (H + H).clifford_conductor() 1 >>> (H + H + H).clifford_conductor() 1 >>> (H + H + H + H).clifford_conductor() 1
- clifford_invariant(p)[source]¶
Return the Clifford invariant.
This is the class in the Brauer group of the Clifford algebra for even dimension, of the even Clifford Algebra for odd dimension.
See Lam (AMS GSM 67) p. 117 for the definition, and p. 119 for the formula relating it to the Hasse invariant.
EXAMPLES:
For hyperbolic spaces, the Clifford invariant is +1:
sage: # needs sage.libs.pari sage: H = QuadraticForm(ZZ, 2, [0, 1, 0]) sage: H.clifford_invariant(2) 1 sage: (H + H).clifford_invariant(2) 1 sage: (H + H + H).clifford_invariant(2) 1 sage: (H + H + H + H).clifford_invariant(2) 1
>>> from sage.all import * >>> # needs sage.libs.pari >>> H = QuadraticForm(ZZ, Integer(2), [Integer(0), Integer(1), Integer(0)]) >>> H.clifford_invariant(Integer(2)) 1 >>> (H + H).clifford_invariant(Integer(2)) 1 >>> (H + H + H).clifford_invariant(Integer(2)) 1 >>> (H + H + H + H).clifford_invariant(Integer(2)) 1
- coefficients()[source]¶
Return the matrix of upper triangular coefficients, by reading across the rows from the main diagonal.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.coefficients() [1, 2, 3]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.coefficients() [1, 2, 3]
- complementary_subform_to_vector(v)[source]¶
Find the \((n-1)\)-dimensional quadratic form orthogonal to the vector \(v\).
Note
This is usually not a direct summand!
Note
There is a minor difference in the cancellation code here (form the C++ version) since the notation
Q[i,j]
indexes coefficients of the quadratic polynomial here, not the symmetric matrix. Also, it produces a better splitting now, for the full lattice (as opposed to a sublattice in the C++ code) since we now extend \(v\) to a unimodular matrix.INPUT:
v
– list ofself.dim()
integers
OUTPUT: a
QuadraticForm
over \(\ZZ\)EXAMPLES:
sage: Q1 = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q1.complementary_subform_to_vector([1,0,0,0]) Quadratic form in 3 variables over Integer Ring with coefficients: [ 7 0 0 ] [ * 5 0 ] [ * * 3 ]
>>> from sage.all import * >>> Q1 = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q1.complementary_subform_to_vector([Integer(1),Integer(0),Integer(0),Integer(0)]) Quadratic form in 3 variables over Integer Ring with coefficients: [ 7 0 0 ] [ * 5 0 ] [ * * 3 ]
sage: Q1.complementary_subform_to_vector([1,1,0,0]) Quadratic form in 3 variables over Integer Ring with coefficients: [ 7 0 0 ] [ * 5 0 ] [ * * 12 ]
>>> from sage.all import * >>> Q1.complementary_subform_to_vector([Integer(1),Integer(1),Integer(0),Integer(0)]) Quadratic form in 3 variables over Integer Ring with coefficients: [ 7 0 0 ] [ * 5 0 ] [ * * 12 ]
sage: Q1.complementary_subform_to_vector([1,1,1,1]) Quadratic form in 3 variables over Integer Ring with coefficients: [ 880 -480 -160 ] [ * 624 -96 ] [ * * 240 ]
>>> from sage.all import * >>> Q1.complementary_subform_to_vector([Integer(1),Integer(1),Integer(1),Integer(1)]) Quadratic form in 3 variables over Integer Ring with coefficients: [ 880 -480 -160 ] [ * 624 -96 ] [ * * 240 ]
- compute_definiteness()[source]¶
Compute whether the given quadratic form is positive-definite, negative-definite, indefinite, degenerate, or the zero form.
This caches one of the following strings in
self.__definiteness_string
: “pos_def”, “neg_def”, “indef”, “zero”, “degenerate”. It is called from all routines like:is_positive_definite()
,is_negative_definite()
,is_indefinite()
, etc.Note
A degenerate form is considered neither definite nor indefinite.
Note
The zero-dimensional form is considered both positive definite and negative definite.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1]) sage: Q.compute_definiteness() sage: Q.is_positive_definite() True sage: Q.is_negative_definite() False sage: Q.is_indefinite() False sage: Q.is_definite() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.compute_definiteness() >>> Q.is_positive_definite() True >>> Q.is_negative_definite() False >>> Q.is_indefinite() False >>> Q.is_definite() True
sage: Q = DiagonalQuadraticForm(ZZ, []) sage: Q.compute_definiteness() sage: Q.is_positive_definite() True sage: Q.is_negative_definite() True sage: Q.is_indefinite() False sage: Q.is_definite() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, []) >>> Q.compute_definiteness() >>> Q.is_positive_definite() True >>> Q.is_negative_definite() True >>> Q.is_indefinite() False >>> Q.is_definite() True
sage: Q = DiagonalQuadraticForm(ZZ, [1,0,-1]) sage: Q.compute_definiteness() sage: Q.is_positive_definite() False sage: Q.is_negative_definite() False sage: Q.is_indefinite() False sage: Q.is_definite() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(0),-Integer(1)]) >>> Q.compute_definiteness() >>> Q.is_positive_definite() False >>> Q.is_negative_definite() False >>> Q.is_indefinite() False >>> Q.is_definite() False
- compute_definiteness_string_by_determinants()[source]¶
Compute the (positive) definiteness of a quadratic form by looking at the signs of all of its upper-left subdeterminants. See also
compute_definiteness()
for more documentation.OUTPUT: string describing the definiteness
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1]) sage: Q.compute_definiteness_string_by_determinants() 'pos_def'
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.compute_definiteness_string_by_determinants() 'pos_def'
sage: Q = DiagonalQuadraticForm(ZZ, []) sage: Q.compute_definiteness_string_by_determinants() 'zero'
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, []) >>> Q.compute_definiteness_string_by_determinants() 'zero'
sage: Q = DiagonalQuadraticForm(ZZ, [1,0,-1]) sage: Q.compute_definiteness_string_by_determinants() 'degenerate'
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(0),-Integer(1)]) >>> Q.compute_definiteness_string_by_determinants() 'degenerate'
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) sage: Q.compute_definiteness_string_by_determinants() 'indefinite'
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(1)]) >>> Q.compute_definiteness_string_by_determinants() 'indefinite'
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-1]) sage: Q.compute_definiteness_string_by_determinants() 'neg_def'
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [-Integer(1),-Integer(1)]) >>> Q.compute_definiteness_string_by_determinants() 'neg_def'
- content()[source]¶
Return the GCD of the coefficients of the quadratic form.
Warning
Only works over Euclidean domains (probably just \(\ZZ\)).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1, 1]) sage: Q.matrix().gcd() 2 sage: Q.content() 1 sage: DiagonalQuadraticForm(ZZ, [1, 1]).is_primitive() True sage: DiagonalQuadraticForm(ZZ, [2, 4]).is_primitive() False sage: DiagonalQuadraticForm(ZZ, [2, 4]).primitive() Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 2 ]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1), Integer(1)]) >>> Q.matrix().gcd() 2 >>> Q.content() 1 >>> DiagonalQuadraticForm(ZZ, [Integer(1), Integer(1)]).is_primitive() True >>> DiagonalQuadraticForm(ZZ, [Integer(2), Integer(4)]).is_primitive() False >>> DiagonalQuadraticForm(ZZ, [Integer(2), Integer(4)]).primitive() Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 2 ]
- conway_cross_product_doubled_power(p)[source]¶
Compute twice the power of \(p\) which evaluates the ‘cross product’ term in Conway’s mass formula.
INPUT:
p
– a prime number > 0
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8)) sage: Q.conway_cross_product_doubled_power(2) 18 sage: Q.conway_cross_product_doubled_power(3) 10 sage: Q.conway_cross_product_doubled_power(5) 6 sage: Q.conway_cross_product_doubled_power(7) 6 sage: Q.conway_cross_product_doubled_power(11) 0 sage: Q.conway_cross_product_doubled_power(13) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(8))) >>> Q.conway_cross_product_doubled_power(Integer(2)) 18 >>> Q.conway_cross_product_doubled_power(Integer(3)) 10 >>> Q.conway_cross_product_doubled_power(Integer(5)) 6 >>> Q.conway_cross_product_doubled_power(Integer(7)) 6 >>> Q.conway_cross_product_doubled_power(Integer(11)) 0 >>> Q.conway_cross_product_doubled_power(Integer(13)) 0
- conway_diagonal_factor(p)[source]¶
Compute the diagonal factor of Conway’s \(p\)-mass.
INPUT:
p
– a prime number > 0
OUTPUT: a rational number > 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,6)) sage: Q.conway_diagonal_factor(3) 81/256
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(6))) >>> Q.conway_diagonal_factor(Integer(3)) 81/256
- conway_mass()[source]¶
Compute the mass by using the Conway-Sloane mass formula.
OUTPUT: a rational number > 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.conway_mass() # needs sage.symbolic 1/48 sage: Q = DiagonalQuadraticForm(ZZ, [7,1,1]) sage: Q.conway_mass() # needs sage.symbolic 3/16 sage: Q = QuadraticForm(ZZ, 3, [7, 2, 2, 2, 0, 2]) + DiagonalQuadraticForm(ZZ, [1]) sage: Q.conway_mass() # needs sage.symbolic 3/32 sage: Q = QuadraticForm(Matrix(ZZ, 2, [2,1,1,2])) sage: Q.conway_mass() # needs sage.symbolic 1/12
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.conway_mass() # needs sage.symbolic 1/48 >>> Q = DiagonalQuadraticForm(ZZ, [Integer(7),Integer(1),Integer(1)]) >>> Q.conway_mass() # needs sage.symbolic 3/16 >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(7), Integer(2), Integer(2), Integer(2), Integer(0), Integer(2)]) + DiagonalQuadraticForm(ZZ, [Integer(1)]) >>> Q.conway_mass() # needs sage.symbolic 3/32 >>> Q = QuadraticForm(Matrix(ZZ, Integer(2), [Integer(2),Integer(1),Integer(1),Integer(2)])) >>> Q.conway_mass() # needs sage.symbolic 1/12
- conway_octane_of_this_unimodular_Jordan_block_at_2()[source]¶
Determines the ‘octane’ of this full unimodular Jordan block at the prime \(p=2\). This is an invariant defined (mod 8), ad.
This assumes that the form is given as a block diagonal form with unimodular blocks of size \(\leq 2\) and the \(1 \times 1\) blocks are all in the upper leftmost position.
OUTPUT: integer \(0 \leq x \leq 7\)
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.conway_octane_of_this_unimodular_Jordan_block_at_2() 0 sage: Q = DiagonalQuadraticForm(ZZ, [1,5,13]) sage: Q.conway_octane_of_this_unimodular_Jordan_block_at_2() 3 sage: Q = DiagonalQuadraticForm(ZZ, [3,7,13]) sage: Q.conway_octane_of_this_unimodular_Jordan_block_at_2() 7
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.conway_octane_of_this_unimodular_Jordan_block_at_2() 0 >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(5),Integer(13)]) >>> Q.conway_octane_of_this_unimodular_Jordan_block_at_2() 3 >>> Q = DiagonalQuadraticForm(ZZ, [Integer(3),Integer(7),Integer(13)]) >>> Q.conway_octane_of_this_unimodular_Jordan_block_at_2() 7
- conway_p_mass(p)[source]¶
Compute Conway’s \(p\)-mass.
INPUT:
p
– a prime number > 0
OUTPUT: a rational number > 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1, 6)) sage: Q.conway_p_mass(2) 16/3 sage: Q.conway_p_mass(3) 729/256
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1), Integer(6))) >>> Q.conway_p_mass(Integer(2)) 16/3 >>> Q.conway_p_mass(Integer(3)) 729/256
- conway_species_list_at_2()[source]¶
Return an integer called the ‘species’ which determines the type of the orthogonal group over the finite field \(\GF{p}\).
This assumes that the given quadratic form is a unimodular Jordan block at an odd prime \(p\). When the dimension is odd then this number is always positive, otherwise it may be positive or negative.
Note
The species of a zero dimensional form is always 0+, so we interpret the return value of zero as positive here! =)
OUTPUT: list of integers
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,10)) sage: Q.conway_species_list_at_2() [1, 5, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(10))) >>> Q.conway_species_list_at_2() [1, 5, 1, 1, 1, 1]
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8)) sage: Q.conway_species_list_at_2() [1, 3, 1, 1, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(8))) >>> Q.conway_species_list_at_2() [1, 3, 1, 1, 1]
- conway_species_list_at_odd_prime(p)[source]¶
Return an integer called the ‘species’ which determines the type of the orthogonal group over the finite field \(\GF{p}\).
This assumes that the given quadratic form is a unimodular Jordan block at an odd prime \(p\). When the dimension is odd then this number is always positive, otherwise it may be positive or negative (or zero, but that is considered positive by convention).
Note
The species of a zero dimensional form is always 0+, so we interpret the return value of zero as positive here! =)
INPUT:
p
– a positive prime number
OUTPUT: list of integers
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,10)) sage: Q.conway_species_list_at_odd_prime(3) [6, 2, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(10))) >>> Q.conway_species_list_at_odd_prime(Integer(3)) [6, 2, 1]
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8)) sage: Q.conway_species_list_at_odd_prime(3) [5, 2] sage: Q.conway_species_list_at_odd_prime(5) [-6, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(8))) >>> Q.conway_species_list_at_odd_prime(Integer(3)) [5, 2] >>> Q.conway_species_list_at_odd_prime(Integer(5)) [-6, 1]
- conway_standard_mass()[source]¶
Return the infinite product of the standard mass factors.
OUTPUT: a rational number > 0
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [2, -2, 0, 3, -5, 4]) sage: Q.conway_standard_mass() # needs sage.symbolic 1/6
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(2), -Integer(2), Integer(0), Integer(3), -Integer(5), Integer(4)]) >>> Q.conway_standard_mass() # needs sage.symbolic 1/6
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.conway_standard_mass() # needs sage.symbolic 1/6
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.conway_standard_mass() # needs sage.symbolic 1/6
- conway_standard_p_mass(p)[source]¶
Compute the standard (generic) Conway-Sloane \(p\)-mass.
INPUT:
p
– a prime number > 0
OUTPUT: a rational number > 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.conway_standard_p_mass(2) 2/3
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.conway_standard_p_mass(Integer(2)) 2/3
- conway_type_factor()[source]¶
This is a special factor only present in the mass formula when \(p=2\).
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8)) sage: Q.conway_type_factor() 4
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, range(Integer(1),Integer(8))) >>> Q.conway_type_factor() 4
- count_congruence_solutions(p, k, m, zvec, nzvec)[source]¶
Count all solutions of \(Q(x) = m\) (mod \(p^k\)) satisfying the additional congruence conditions described in
QuadraticForm.count_congruence_solutions_as_vector()
.INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers inrange(self.dim())
, orNone
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions(3, 1, 0, None, None) 15
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions(Integer(3), Integer(1), Integer(0), None, None) 15
- count_congruence_solutions__bad_type(p, k, m, zvec, nzvec)[source]¶
Count the bad-type solutions of \(Q(x) = m\) (mod \(p^k\)) satisfying the additional congruence conditions described in
QuadraticForm.count_congruence_solutions_as_vector()
.INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers up to dim(\(Q\))
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions__bad_type(3, 1, 0, None, None) 2
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions__bad_type(Integer(3), Integer(1), Integer(0), None, None) 2
- count_congruence_solutions__bad_type_I(p, k, m, zvec, nzvec)[source]¶
Count the bad-typeI solutions of \(Q(x) = m\) (mod \(p^k\)) satisfying the additional congruence conditions described in
QuadraticForm.count_congruence_solutions_as_vector()
.INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers up to dim(\(Q\))
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions__bad_type_I(3, 1, 0, None, None) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions__bad_type_I(Integer(3), Integer(1), Integer(0), None, None) 0
- count_congruence_solutions__bad_type_II(p, k, m, zvec, nzvec)[source]¶
Count the bad-typeII solutions of \(Q(x) = m\) (mod \(p^k\)) satisfying the additional congruence conditions described in
QuadraticForm.count_congruence_solutions_as_vector()
.INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers up to dim(\(Q\))
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions__bad_type_II(3, 1, 0, None, None) 2
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions__bad_type_II(Integer(3), Integer(1), Integer(0), None, None) 2
- count_congruence_solutions__good_type(p, k, m, zvec, nzvec)[source]¶
Count the good-type solutions of \(Q(x) = m\) (mod \(p^k\)) satisfying the additional congruence conditions described in
QuadraticForm.count_congruence_solutions_as_vector()
.INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers up to dim(\(Q\))
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions__good_type(3, 1, 0, None, None) 12
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions__good_type(Integer(3), Integer(1), Integer(0), None, None) 12
- count_congruence_solutions__zero_type(p, k, m, zvec, nzvec)[source]¶
Count the zero-type solutions of \(Q(x) = m\) (mod \(p^k\)) satisfying the additional congruence conditions described in
QuadraticForm.count_congruence_solutions_as_vector()
.INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers up to dim(\(Q\))
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions__zero_type(3, 1, 0, None, None) 1
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions__zero_type(Integer(3), Integer(1), Integer(0), None, None) 1
- count_congruence_solutions_as_vector(p, k, m, zvec, nzvec)[source]¶
Return the number of integer solution vectors \(x\) satisfying the congruence \(Q(x) = m\) (mod \(p^k\)) of each solution type (i.e. All, Good, Zero, Bad, BadI, BadII) which satisfy the additional congruence conditions of having certain coefficients = 0 (mod \(p\)) and certain collections of coefficients not congruent to the zero vector (mod \(p\)).
A solution vector \(x\) satisfies the additional congruence conditions specified by
zvec
andnzvec
(and therefore is counted) iff both of the following conditions hold:\(x_i = 0\) (mod \(p\)) for all \(i\) in
zvec
\(x_i \neq 0\) (mod \(p\)) for all \(i\) in
nzvec
REFERENCES:
See Hanke’s (????) paper “Local Densities and explicit bounds…”, p??? for the definitions of the solution types and congruence conditions.
INPUT:
p
– prime number > 0k
– integer > 0m
– integer (depending only on mod \(p^k\))zvec
,nzvec
– lists of integers inrange(self.dim())
, orNone
OUTPUT:
a list of six integers \(\geq 0\) representing the solution types: [All, Good, Zero, Bad, BadI, BadII]
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.count_congruence_solutions_as_vector(3, 1, 1, [], []) [0, 0, 0, 0, 0, 0] sage: Q.count_congruence_solutions_as_vector(3, 1, 1, None, []) [0, 0, 0, 0, 0, 0] sage: Q.count_congruence_solutions_as_vector(3, 1, 1, [], None) [6, 6, 0, 0, 0, 0] sage: Q.count_congruence_solutions_as_vector(3, 1, 1, None, None) [6, 6, 0, 0, 0, 0] sage: Q.count_congruence_solutions_as_vector(3, 1, 2, None, None) [6, 6, 0, 0, 0, 0] sage: Q.count_congruence_solutions_as_vector(3, 1, 0, None, None) [15, 12, 1, 2, 0, 2]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.count_congruence_solutions_as_vector(Integer(3), Integer(1), Integer(1), [], []) [0, 0, 0, 0, 0, 0] >>> Q.count_congruence_solutions_as_vector(Integer(3), Integer(1), Integer(1), None, []) [0, 0, 0, 0, 0, 0] >>> Q.count_congruence_solutions_as_vector(Integer(3), Integer(1), Integer(1), [], None) [6, 6, 0, 0, 0, 0] >>> Q.count_congruence_solutions_as_vector(Integer(3), Integer(1), Integer(1), None, None) [6, 6, 0, 0, 0, 0] >>> Q.count_congruence_solutions_as_vector(Integer(3), Integer(1), Integer(2), None, None) [6, 6, 0, 0, 0, 0] >>> Q.count_congruence_solutions_as_vector(Integer(3), Integer(1), Integer(0), None, None) [15, 12, 1, 2, 0, 2]
- count_modp_solutions__by_Gauss_sum(p, m)[source]¶
Return the number of solutions of \(Q(x) = m\) (mod \(p\)) of a non-degenerate quadratic form over the finite field \(\ZZ/p\ZZ\), where \(p\) is a prime number > 2.
Note
We adopt the useful convention that a zero-dimensional quadratic form has exactly one solution always (i.e. the empty vector).
These are defined in Table 1 on p363 of Hanke’s “Local Densities…” paper.
INPUT:
p
– a prime number > 2m
– integer
OUTPUT: integer \(\geq 0\)
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: [Q.count_modp_solutions__by_Gauss_sum(3, m) for m in range(3)] [9, 6, 12] sage: Q = DiagonalQuadraticForm(ZZ, [1,1,2]) sage: [Q.count_modp_solutions__by_Gauss_sum(3, m) for m in range(3)] [9, 12, 6]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> [Q.count_modp_solutions__by_Gauss_sum(Integer(3), m) for m in range(Integer(3))] [9, 6, 12] >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(2)]) >>> [Q.count_modp_solutions__by_Gauss_sum(Integer(3), m) for m in range(Integer(3))] [9, 12, 6]
- delta()[source]¶
Return the omega of the adjoint form.
This is the same as the omega of the reciprocal form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,37]) sage: Q.delta() 148
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(37)]) >>> Q.delta() 148
- det()[source]¶
Return the determinant of the Gram matrix of \(2\cdot Q\), or equivalently the determinant of the Hessian matrix of \(Q\).
Note
This is always defined over the same ring as the quadratic form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.det() 8
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.det() 8
- dim()[source]¶
Return the number of variables of the quadratic form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.dim() 2 sage: parent(Q.dim()) Integer Ring sage: Q = QuadraticForm(Q.matrix()) sage: Q.dim() 2 sage: parent(Q.dim()) Integer Ring
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.dim() 2 >>> parent(Q.dim()) Integer Ring >>> Q = QuadraticForm(Q.matrix()) >>> Q.dim() 2 >>> parent(Q.dim()) Integer Ring
- disc()[source]¶
Return the discriminant of the quadratic form, defined as
\((-1)^n {\rm det}(B)\) for even dimension \(2n\)
\({\rm det}(B)/2\) for odd dimension
where \(2Q(x) = x^t B x\).
This agrees with the usual discriminant for binary and ternary quadratic forms.
EXAMPLES:
sage: DiagonalQuadraticForm(ZZ, [1]).disc() 1 sage: DiagonalQuadraticForm(ZZ, [1,1]).disc() -4 sage: DiagonalQuadraticForm(ZZ, [1,1,1]).disc() 4 sage: DiagonalQuadraticForm(ZZ, [1,1,1,1]).disc() 16
>>> from sage.all import * >>> DiagonalQuadraticForm(ZZ, [Integer(1)]).disc() 1 >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]).disc() -4 >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]).disc() 4 >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]).disc() 16
- discrec()[source]¶
Return the discriminant of the reciprocal form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,37]) sage: Q.disc() 148 sage: Q.discrec() 5476 sage: [4 * 37, 4 * 37^2] [148, 5476]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(37)]) >>> Q.disc() 148 >>> Q.discrec() 5476 >>> [Integer(4) * Integer(37), Integer(4) * Integer(37)**Integer(2)] [148, 5476]
- divide_variable(c, i, in_place=False)[source]¶
Replace the variables \(x_i\) by \((x_i)/c\) in the quadratic form (replacing the original form if the
in_place
flag is True).Here \(c\) must be an element of the base ring defining the quadratic form, and the division must be defined in the base ring.
INPUT:
c
– an element ofself.base_ring()
i
– integer \(\geq 0\)
OUTPUT:
a
QuadraticForm
(by default, otherwise none)EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,9,5,7]) sage: Q.divide_variable(3, 1) Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 1 0 0 ] [ * * 5 0 ] [ * * * 7 ]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(9),Integer(5),Integer(7)]) >>> Q.divide_variable(Integer(3), Integer(1)) Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 1 0 0 ] [ * * 5 0 ] [ * * * 7 ]
- elementary_substitution(c, i, j, in_place=False)[source]¶
Perform the substitution \(x_i \longmapsto x_i + c\cdot x_j\) (replacing the original form if the
in_place
flag is True).INPUT:
c
– an element ofself.base_ring()
i
,j
– integers \(\geq 0\)
OUTPUT:
a
QuadraticForm
(by default, otherwise none)EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(1,11)); Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 4 ] [ * 5 6 7 ] [ * * 8 9 ] [ * * * 10 ] sage: Q.elementary_substitution(c=1, i=0, j=3) Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 6 ] [ * 5 6 9 ] [ * * 8 12 ] [ * * * 15 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(1),Integer(11))); Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 4 ] [ * 5 6 7 ] [ * * 8 9 ] [ * * * 10 ] >>> Q.elementary_substitution(c=Integer(1), i=Integer(0), j=Integer(3)) Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 6 ] [ * 5 6 9 ] [ * * 8 12 ] [ * * * 15 ]
sage: R = QuadraticForm(ZZ, 4, range(1,11)); R Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 4 ] [ * 5 6 7 ] [ * * 8 9 ] [ * * * 10 ]
>>> from sage.all import * >>> R = QuadraticForm(ZZ, Integer(4), range(Integer(1),Integer(11))); R Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 4 ] [ * 5 6 7 ] [ * * 8 9 ] [ * * * 10 ]
sage: M = Matrix(ZZ, 4, 4, [1,0,0,1, 0,1,0,0, 0,0,1,0, 0,0,0,1]); M [1 0 0 1] [0 1 0 0] [0 0 1 0] [0 0 0 1] sage: R(M) Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 6 ] [ * 5 6 9 ] [ * * 8 12 ] [ * * * 15 ]
>>> from sage.all import * >>> M = Matrix(ZZ, Integer(4), Integer(4), [Integer(1),Integer(0),Integer(0),Integer(1), Integer(0),Integer(1),Integer(0),Integer(0), Integer(0),Integer(0),Integer(1),Integer(0), Integer(0),Integer(0),Integer(0),Integer(1)]); M [1 0 0 1] [0 1 0 0] [0 0 1 0] [0 0 0 1] >>> R(M) Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 2 3 6 ] [ * 5 6 9 ] [ * * 8 12 ] [ * * * 15 ]
- extract_variables(QF, var_indices)[source]¶
Extract the variables (in order) whose indices are listed in
var_indices
, to give a new quadratic form.INPUT:
var_indices
– list of integers \(\geq 0\)
OUTPUT: a
QuadraticForm
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(10)); Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 0 1 2 3 ] [ * 4 5 6 ] [ * * 7 8 ] [ * * * 9 ] sage: Q.extract_variables([1,3]) Quadratic form in 2 variables over Integer Ring with coefficients: [ 4 6 ] [ * 9 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(10))); Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 0 1 2 3 ] [ * 4 5 6 ] [ * * 7 8 ] [ * * * 9 ] >>> Q.extract_variables([Integer(1),Integer(3)]) Quadratic form in 2 variables over Integer Ring with coefficients: [ 4 6 ] [ * 9 ]
- find_entry_with_minimal_scale_at_prime(p)[source]¶
Find the entry of the quadratic form with minimal scale at the prime \(p\), preferring diagonal entries in case of a tie.
(I.e. If we write the quadratic form as a symmetric matrix \(M\), then this entry
M[i,j]
has the minimal valuation at the prime \(p\).)Note
This answer is independent of the kind of matrix (Gram or Hessian) associated to the form.
INPUT:
p
– a prime number > 0
OUTPUT: a pair of integers \(\geq 0\)
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [6, 2, 20]); Q Quadratic form in 2 variables over Integer Ring with coefficients: [ 6 2 ] [ * 20 ] sage: Q.find_entry_with_minimal_scale_at_prime(2) (0, 1) sage: Q.find_entry_with_minimal_scale_at_prime(3) (1, 1) sage: Q.find_entry_with_minimal_scale_at_prime(5) (0, 0)
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(6), Integer(2), Integer(20)]); Q Quadratic form in 2 variables over Integer Ring with coefficients: [ 6 2 ] [ * 20 ] >>> Q.find_entry_with_minimal_scale_at_prime(Integer(2)) (0, 1) >>> Q.find_entry_with_minimal_scale_at_prime(Integer(3)) (1, 1) >>> Q.find_entry_with_minimal_scale_at_prime(Integer(5)) (0, 0)
- find_p_neighbor_from_vec(p, y, return_matrix=False)[source]¶
Return the \(p\)-neighbor of
self
defined byy
.Let \((L,q)\) be a lattice with \(b(L,L) \subseteq \ZZ\) which is maximal at \(p\). Let \(y \in L\) with \(b(y,y) \in p^2\ZZ\) then the \(p\)-neighbor of \(L\) at \(y\) is given by \(\ZZ y/p + L_y\) where \(L_y = \{x \in L | b(x,y) \in p \ZZ \}\) and \(b(x,y) = q(x+y)-q(x)-q(y)\) is the bilinear form associated to \(q\).
INPUT:
p
– a prime numbery
– a vector with \(q(y) \in p \ZZ\)odd
– boolean (default:False
); if \(p=2\), return also odd neighborsreturn_matrix
– boolean (default:False
); return the transformation matrix instead of the quadratic form
EXAMPLES:
sage: # needs sage.libs.pari sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: v = vector([0,2,1,1]) sage: X = Q.find_p_neighbor_from_vec(3, v); X Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 1 4 4 ] [ * * 5 12 ] [ * * * 9 ] sage: B = Q.find_p_neighbor_from_vec(3, v, return_matrix=True) sage: Q(B) == X True
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> v = vector([Integer(0),Integer(2),Integer(1),Integer(1)]) >>> X = Q.find_p_neighbor_from_vec(Integer(3), v); X Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 0 0 ] [ * 1 4 4 ] [ * * 5 12 ] [ * * * 9 ] >>> B = Q.find_p_neighbor_from_vec(Integer(3), v, return_matrix=True) >>> Q(B) == X True
Since the base ring and the domain are not yet separate, for rational, half integral forms we just pretend the base ring is \(\ZZ\):
sage: # needs sage.libs.pari sage: Q = QuadraticForm(QQ, matrix.diagonal([1,1,1,1])) sage: v = vector([1,1,1,1]) sage: Q.find_p_neighbor_from_vec(2, v) Quadratic form in 4 variables over Rational Field with coefficients: [ 1/2 1 1 1 ] [ * 1 1 2 ] [ * * 1 2 ] [ * * * 2 ]
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q = QuadraticForm(QQ, matrix.diagonal([Integer(1),Integer(1),Integer(1),Integer(1)])) >>> v = vector([Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.find_p_neighbor_from_vec(Integer(2), v) Quadratic form in 4 variables over Rational Field with coefficients: [ 1/2 1 1 1 ] [ * 1 1 2 ] [ * * 1 2 ] [ * * * 2 ]
- find_primitive_p_divisible_vector__next(p, v=None)[source]¶
Find the next \(p\)-primitive vector (up to scaling) in \(L/pL\) whose value is \(p\)-divisible, where the last vector returned was \(v\). For an initial call, no \(v\) needs to be passed.
Return vectors whose last nonzero entry is normalized to 0 or 1 (so no lines are counted repeatedly). The ordering is by increasing the first non-normalized entry. If we have tested all (lines of) vectors, then return None.
OUTPUT: vector or None
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [10,1,4]) sage: v = Q.find_primitive_p_divisible_vector__next(5); v (1, 1) sage: v = Q.find_primitive_p_divisible_vector__next(5, v); v (1, 0) sage: v = Q.find_primitive_p_divisible_vector__next(5, v); v sage: v = Q.find_primitive_p_divisible_vector__next(2) ; v (0, 1) sage: v = Q.find_primitive_p_divisible_vector__next(2, v) ; v (1, 0) sage: Q = QuadraticForm(QQ, matrix.diagonal([1,1,1,1])) sage: v = Q.find_primitive_p_divisible_vector__next(2) sage: Q(v) 2
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(10),Integer(1),Integer(4)]) >>> v = Q.find_primitive_p_divisible_vector__next(Integer(5)); v (1, 1) >>> v = Q.find_primitive_p_divisible_vector__next(Integer(5), v); v (1, 0) >>> v = Q.find_primitive_p_divisible_vector__next(Integer(5), v); v >>> v = Q.find_primitive_p_divisible_vector__next(Integer(2)) ; v (0, 1) >>> v = Q.find_primitive_p_divisible_vector__next(Integer(2), v) ; v (1, 0) >>> Q = QuadraticForm(QQ, matrix.diagonal([Integer(1),Integer(1),Integer(1),Integer(1)])) >>> v = Q.find_primitive_p_divisible_vector__next(Integer(2)) >>> Q(v) 2
- find_primitive_p_divisible_vector__random(p)[source]¶
Find a random \(p\)-primitive vector in \(L/pL\) whose value is \(p\)-divisible.
Note
Since there are about \(p^{(n-2)}\) of these lines, we have a \(1/p\) chance of randomly finding an appropriate vector.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [10,1,4]) sage: v = Q.find_primitive_p_divisible_vector__random(5) sage: tuple(v) in ((1, 0), (1, 1), (2, 0), (2, 2), (3, 0), (3, 3), (4, 0), (4, 4)) True sage: 5.divides(Q(v)) True sage: Q = QuadraticForm(QQ, matrix.diagonal([1,1,1,1])) sage: v = Q.find_primitive_p_divisible_vector__random(2) sage: Q(v) 2
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(10),Integer(1),Integer(4)]) >>> v = Q.find_primitive_p_divisible_vector__random(Integer(5)) >>> tuple(v) in ((Integer(1), Integer(0)), (Integer(1), Integer(1)), (Integer(2), Integer(0)), (Integer(2), Integer(2)), (Integer(3), Integer(0)), (Integer(3), Integer(3)), (Integer(4), Integer(0)), (Integer(4), Integer(4))) True >>> Integer(5).divides(Q(v)) True >>> Q = QuadraticForm(QQ, matrix.diagonal([Integer(1),Integer(1),Integer(1),Integer(1)])) >>> v = Q.find_primitive_p_divisible_vector__random(Integer(2)) >>> Q(v) 2
- static from_polynomial(poly)[source]¶
Construct a
QuadraticForm
from a multivariate polynomial. Inverse ofpolynomial()
.EXAMPLES:
sage: R.<x,y,z> = ZZ[] sage: f = 5*x^2 - x*z - 3*y*z - 2*y^2 + 9*z^2 sage: Q = QuadraticForm.from_polynomial(f); Q Quadratic form in 3 variables over Integer Ring with coefficients: [ 5 0 -1 ] [ * -2 -3 ] [ * * 9 ] sage: Q.polynomial() 5*x0^2 - 2*x1^2 - x0*x2 - 3*x1*x2 + 9*x2^2 sage: Q.polynomial()(R.gens()) == f True
>>> from sage.all import * >>> R = ZZ['x, y, z']; (x, y, z,) = R._first_ngens(3) >>> f = Integer(5)*x**Integer(2) - x*z - Integer(3)*y*z - Integer(2)*y**Integer(2) + Integer(9)*z**Integer(2) >>> Q = QuadraticForm.from_polynomial(f); Q Quadratic form in 3 variables over Integer Ring with coefficients: [ 5 0 -1 ] [ * -2 -3 ] [ * * 9 ] >>> Q.polynomial() 5*x0^2 - 2*x1^2 - x0*x2 - 3*x1*x2 + 9*x2^2 >>> Q.polynomial()(R.gens()) == f True
The method fails if the given polynomial is not a quadratic form:
sage: QuadraticForm.from_polynomial(x^3 + x*z + 5*y^2) Traceback (most recent call last): ... ValueError: polynomial has monomials of degree != 2
>>> from sage.all import * >>> QuadraticForm.from_polynomial(x**Integer(3) + x*z + Integer(5)*y**Integer(2)) Traceback (most recent call last): ... ValueError: polynomial has monomials of degree != 2
- gcd()[source]¶
Return the greatest common divisor of the coefficients of the quadratic form (as a polynomial).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(1, 21, 2)) sage: Q.gcd() 1 sage: Q = QuadraticForm(ZZ, 4, range(0, 20, 2)) sage: Q.gcd() 2
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(1), Integer(21), Integer(2))) >>> Q.gcd() 1 >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(0), Integer(20), Integer(2))) >>> Q.gcd() 2
- static genera(sig_pair, determinant, max_scale=None, even=False)[source]¶
Return a list of all global genera with the given conditions.
Here a genus is called global if it is non-empty.
INPUT:
sig_pair
– a pair of nonnegative integers giving the signaturedeterminant
– integer; the sign is ignoredmax_scale
– (default:None
) an integer; the maximum scale of a jordan blockeven
– boolean (default:False
)
OUTPUT:
A list of all (non-empty) global genera with the given conditions.
EXAMPLES:
sage: QuadraticForm.genera((4,0), 125, even=True) [Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^1 5^3, Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^-2 5^1 25^-1, Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^2 5^1 25^1, Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^3 125^1]
>>> from sage.all import * >>> QuadraticForm.genera((Integer(4),Integer(0)), Integer(125), even=True) [Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^1 5^3, Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^-2 5^1 25^-1, Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^2 5^1 25^1, Genus of None Signature: (4, 0) Genus symbol at 2: 1^-4 Genus symbol at 5: 1^3 125^1]
- global_genus_symbol()[source]¶
Return the genus of two times a quadratic form over \(\ZZ\).
These are defined by a collection of local genus symbols (a la Chapter 15 of Conway-Sloane [CS1999]), and a signature.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3,4]) sage: Q.global_genus_symbol() Genus of [2 0 0 0] [0 4 0 0] [0 0 6 0] [0 0 0 8] Signature: (4, 0) Genus symbol at 2: [2^-2 4^1 8^1]_6 Genus symbol at 3: 1^3 3^-1
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3),Integer(4)]) >>> Q.global_genus_symbol() Genus of [2 0 0 0] [0 4 0 0] [0 0 6 0] [0 0 0 8] Signature: (4, 0) Genus symbol at 2: [2^-2 4^1 8^1]_6 Genus symbol at 3: 1^3 3^-1
sage: Q = QuadraticForm(ZZ, 4, range(10)) sage: Q.global_genus_symbol() Genus of [ 0 1 2 3] [ 1 8 5 6] [ 2 5 14 8] [ 3 6 8 18] Signature: (3, 1) Genus symbol at 2: 1^-4 Genus symbol at 563: 1^3 563^-1
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(10))) >>> Q.global_genus_symbol() Genus of [ 0 1 2 3] [ 1 8 5 6] [ 2 5 14 8] [ 3 6 8 18] Signature: (3, 1) Genus symbol at 2: 1^-4 Genus symbol at 563: 1^3 563^-1
- has_equivalent_Jordan_decomposition_at_prime(other, p)[source]¶
Determine if the given quadratic form has a Jordan decomposition equivalent to that of
self
.INPUT:
other
– aQuadraticForm
OUTPUT: boolean
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 1, 0, 3]) sage: Q2 = QuadraticForm(ZZ, 3, [1, 0, 0, 2, -2, 6]) sage: Q3 = QuadraticForm(ZZ, 3, [1, 0, 0, 1, 0, 11]) sage: [Q1.level(), Q2.level(), Q3.level()] [44, 44, 44] sage: # needs sage.libs.pari sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, 2) False sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, 11) False sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, 2) False sage: Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, 11) True sage: Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, 2) True sage: Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, 11) False
>>> from sage.all import * >>> Q1 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(1), Integer(0), Integer(3)]) >>> Q2 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), Integer(0), Integer(2), -Integer(2), Integer(6)]) >>> Q3 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), Integer(0), Integer(1), Integer(0), Integer(11)]) >>> [Q1.level(), Q2.level(), Q3.level()] [44, 44, 44] >>> # needs sage.libs.pari >>> Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, Integer(2)) False >>> Q1.has_equivalent_Jordan_decomposition_at_prime(Q2, Integer(11)) False >>> Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, Integer(2)) False >>> Q1.has_equivalent_Jordan_decomposition_at_prime(Q3, Integer(11)) True >>> Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, Integer(2)) True >>> Q2.has_equivalent_Jordan_decomposition_at_prime(Q3, Integer(11)) False
- has_integral_Gram_matrix()[source]¶
Return whether the quadratic form has an integral Gram matrix (with respect to its base ring).
A warning is issued if the form is defined over a field, since in that case the return is trivially true.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [7,8,9]) sage: Q.has_integral_Gram_matrix() True
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(7),Integer(8),Integer(9)]) >>> Q.has_integral_Gram_matrix() True
sage: Q = QuadraticForm(ZZ, 2, [4,5,6]) sage: Q.has_integral_Gram_matrix() False
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(4),Integer(5),Integer(6)]) >>> Q.has_integral_Gram_matrix() False
- hasse_conductor()[source]¶
Return the Hasse conductor.
This is the product of all primes where the Hasse invariant equals \(-1\).
EXAMPLES:
sage: # needs sage.libs.pari sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.hasse_invariant(2) -1 sage: Q.hasse_invariant(37) -1 sage: Q.hasse_conductor() 74 sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor() # needs sage.libs.pari 1 sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor() # needs sage.libs.pari 10
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q.hasse_invariant(Integer(2)) -1 >>> Q.hasse_invariant(Integer(37)) -1 >>> Q.hasse_conductor() 74 >>> DiagonalQuadraticForm(ZZ, [Integer(1), Integer(1), Integer(1)]).hasse_conductor() # needs sage.libs.pari 1 >>> QuadraticForm(ZZ, Integer(3), [Integer(2), -Integer(2), Integer(0), Integer(2), Integer(0), Integer(5)]).hasse_conductor() # needs sage.libs.pari 10
- hasse_invariant(p)[source]¶
Compute the Hasse invariant at a prime \(p\) or at infinity, as given on p55 of Cassels’s book. If \(Q\) is diagonal with coefficients \(a_i\), then the (Cassels) Hasse invariant is given by
\[c_p = \prod_{i < j} (a_i, a_j)_p\]where \((a,b)_p\) is the Hilbert symbol at \(p\). The underlying quadratic form must be non-degenerate over \(\QQ_p\) for this to make sense.
Warning
This is different from the O’Meara Hasse invariant, which allows \(i \leq j\) in the product. That is given by the method
hasse_invariant__OMeara()
.Note
We should really rename this
hasse_invariant__Cassels
, and sethasse_invariant()
as a front-end to it.INPUT:
p
– a prime number > 0 or \(-1\) for the infinite place
OUTPUT: \(1\) or \(-1\)
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.rational_diagonal_form() Quadratic form in 2 variables over Rational Field with coefficients: [ 1 0 ] [ * 2 ] sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.rational_diagonal_form() Quadratic form in 2 variables over Rational Field with coefficients: [ 1 0 ] [ * 2 ] >>> [Q.hasse_invariant(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] >>> [Q.hasse_invariant__OMeara(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1]
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(1)]) >>> [Q.hasse_invariant(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] >>> [Q.hasse_invariant__OMeara(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1,5]) sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(1),Integer(5)]) >>> [Q.hasse_invariant(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] >>> [Q.hasse_invariant__OMeara(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
sage: x = polygen(ZZ, 'x') sage: K.<a> = NumberField(x^2 - 23) # needs sage.rings.number_field sage: Q = DiagonalQuadraticForm(K, [-a, a + 2]) # needs sage.rings.number_field sage: [Q.hasse_invariant(p) for p in K.primes_above(19)] # needs sage.rings.number_field [-1, 1]
>>> from sage.all import * >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(2) - Integer(23), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field >>> Q = DiagonalQuadraticForm(K, [-a, a + Integer(2)]) # needs sage.rings.number_field >>> [Q.hasse_invariant(p) for p in K.primes_above(Integer(19))] # needs sage.rings.number_field [-1, 1]
- hasse_invariant__OMeara(p)[source]¶
Compute the O’Meara Hasse invariant at a prime \(p\).
This is defined on p167 of O’Meara’s book. If \(Q\) is diagonal with coefficients \(a_i\), then the (Cassels) Hasse invariant is given by
\[c_p = \prod_{i \leq j} (a_i, a_j)_p\]where \((a,b)_p\) is the Hilbert symbol at \(p\).
Warning
This is different from the (Cassels) Hasse invariant, which only allows \(i < j\) in the product. That is given by the method hasse_invariant(p).
INPUT:
p
– a prime number > 0 or \(-1\) for the infinite place
OUTPUT: \(1\) or \(-1\)
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3]) sage: Q.rational_diagonal_form() Quadratic form in 2 variables over Rational Field with coefficients: [ 1 0 ] [ * 2 ] sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(2),Integer(3)]) >>> Q.rational_diagonal_form() Quadratic form in 2 variables over Rational Field with coefficients: [ 1 0 ] [ * 2 ] >>> [Q.hasse_invariant(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] >>> [Q.hasse_invariant__OMeara(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1]
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(1)]) >>> [Q.hasse_invariant(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [1, 1, 1, 1, 1, 1, 1, 1] >>> [Q.hasse_invariant__OMeara(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
sage: Q = DiagonalQuadraticForm(ZZ,[1,-1,-1]) sage: [Q.hasse_invariant(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ,[Integer(1),-Integer(1),-Integer(1)]) >>> [Q.hasse_invariant(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1] >>> [Q.hasse_invariant__OMeara(p) for p in prime_range(Integer(20))] # needs sage.libs.pari [-1, 1, 1, 1, 1, 1, 1, 1]
sage: x = polygen(ZZ, 'x') sage: K.<a> = NumberField(x^2 - 23) # needs sage.rings.number_field sage: Q = DiagonalQuadraticForm(K, [-a, a + 2]) # needs sage.rings.number_field sage: [Q.hasse_invariant__OMeara(p) for p in K.primes_above(19)] # needs sage.rings.number_field [1, 1]
>>> from sage.all import * >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(2) - Integer(23), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field >>> Q = DiagonalQuadraticForm(K, [-a, a + Integer(2)]) # needs sage.rings.number_field >>> [Q.hasse_invariant__OMeara(p) for p in K.primes_above(Integer(19))] # needs sage.rings.number_field [1, 1]
- is_adjoint()[source]¶
Determine if the given form is the adjoint of another form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.is_adjoint() # needs sage.symbolic False sage: Q.adjoint().is_adjoint() True
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q.is_adjoint() # needs sage.symbolic False >>> Q.adjoint().is_adjoint() True
- is_anisotropic(p)[source]¶
Check if the quadratic form is anisotropic over the \(p\)-adic numbers \(\QQ_p\) or \(\RR\).
INPUT:
p
– a prime number > 0 or \(-1\) for the infinite place
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) sage: Q.is_anisotropic(2) # needs sage.libs.pari True sage: Q.is_anisotropic(3) # needs sage.libs.pari True sage: Q.is_anisotropic(5) # needs sage.libs.pari False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]) >>> Q.is_anisotropic(Integer(2)) # needs sage.libs.pari True >>> Q.is_anisotropic(Integer(3)) # needs sage.libs.pari True >>> Q.is_anisotropic(Integer(5)) # needs sage.libs.pari False
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) sage: Q.is_anisotropic(2) # needs sage.libs.pari False sage: Q.is_anisotropic(3) # needs sage.libs.pari False sage: Q.is_anisotropic(5) # needs sage.libs.pari False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(1)]) >>> Q.is_anisotropic(Integer(2)) # needs sage.libs.pari False >>> Q.is_anisotropic(Integer(3)) # needs sage.libs.pari False >>> Q.is_anisotropic(Integer(5)) # needs sage.libs.pari False
sage: [DiagonalQuadraticForm(ZZ, # needs sage.libs.pari ....: [1, -least_quadratic_nonresidue(p)]).is_anisotropic(p) ....: for p in prime_range(3, 30)] [True, True, True, True, True, True, True, True, True]
>>> from sage.all import * >>> [DiagonalQuadraticForm(ZZ, # needs sage.libs.pari ... [Integer(1), -least_quadratic_nonresidue(p)]).is_anisotropic(p) ... for p in prime_range(Integer(3), Integer(30))] [True, True, True, True, True, True, True, True, True]
sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), # needs sage.libs.pari ....: p, -p*least_quadratic_nonresidue(p)]).is_anisotropic(p) ....: for p in prime_range(3, 30)] [True, True, True, True, True, True, True, True, True]
>>> from sage.all import * >>> [DiagonalQuadraticForm(ZZ, [Integer(1), -least_quadratic_nonresidue(p), # needs sage.libs.pari ... p, -p*least_quadratic_nonresidue(p)]).is_anisotropic(p) ... for p in prime_range(Integer(3), Integer(30))] [True, True, True, True, True, True, True, True, True]
- is_definite()[source]¶
Determines if the given quadratic form is (positive or negative) definite.
Note
A degenerate form is considered neither definite nor indefinite.
Note
The zero-dimensional form is considered indefinite.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-3,-5]) sage: Q.is_definite() True sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5]) sage: Q.is_definite() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [-Integer(1),-Integer(3),-Integer(5)]) >>> Q.is_definite() True >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(3),Integer(5)]) >>> Q.is_definite() False
- is_even(allow_rescaling_flag=True)[source]¶
Return true iff after rescaling by some appropriate factor, the form represents no odd integers. For more details, see
parity()
.Requires that \(Q\) is defined over \(\ZZ\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1, 0, 1]) sage: Q.is_even() False sage: Q = QuadraticForm(ZZ, 2, [1, 1, 1]) sage: Q.is_even() True
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1), Integer(0), Integer(1)]) >>> Q.is_even() False >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1), Integer(1), Integer(1)]) >>> Q.is_even() True
- is_globally_equivalent_to(other, return_matrix=False)[source]¶
Determine if the current quadratic form is equivalent to the given form over \(\ZZ\).
If
return_matrix
is True, then we return the transformation matrix \(M\) so thatself(M) == other
.INPUT:
self
,other
– positive definite integral quadratic formsreturn_matrix
– boolean (default:False
); return the transformation matrix instead of a boolean
OUTPUT:
if
return_matrix
isFalse
: a booleanif
return_matrix
isTrue
: eitherFalse
or the transformation matrix
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: M = Matrix(ZZ, 4, 4, [1,2,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]) sage: Q1 = Q(M) sage: Q.is_globally_equivalent_to(Q1) # needs sage.libs.pari True sage: MM = Q.is_globally_equivalent_to(Q1, return_matrix=True) # needs sage.libs.pari sage: Q(MM) == Q1 # needs sage.libs.pari True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> M = Matrix(ZZ, Integer(4), Integer(4), [Integer(1),Integer(2),Integer(0),Integer(0), Integer(0),Integer(1),Integer(0),Integer(0), Integer(0),Integer(0),Integer(1),Integer(0), Integer(0),Integer(0),Integer(0),Integer(1)]) >>> Q1 = Q(M) >>> Q.is_globally_equivalent_to(Q1) # needs sage.libs.pari True >>> MM = Q.is_globally_equivalent_to(Q1, return_matrix=True) # needs sage.libs.pari >>> Q(MM) == Q1 # needs sage.libs.pari True
sage: # needs sage.libs.pari sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q2 = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3]) sage: Q3 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2]) sage: Q1.is_globally_equivalent_to(Q2) False sage: Q1.is_globally_equivalent_to(Q2, return_matrix=True) False sage: Q1.is_globally_equivalent_to(Q3) True sage: M = Q1.is_globally_equivalent_to(Q3, True); M [-1 -1 0] [ 1 1 1] [-1 0 0] sage: Q1(M) == Q3 True
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q1 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q2 = QuadraticForm(ZZ, Integer(3), [Integer(2), Integer(1), Integer(2), Integer(2), Integer(1), Integer(3)]) >>> Q3 = QuadraticForm(ZZ, Integer(3), [Integer(8), Integer(6), Integer(5), Integer(3), Integer(4), Integer(2)]) >>> Q1.is_globally_equivalent_to(Q2) False >>> Q1.is_globally_equivalent_to(Q2, return_matrix=True) False >>> Q1.is_globally_equivalent_to(Q3) True >>> M = Q1.is_globally_equivalent_to(Q3, True); M [-1 -1 0] [ 1 1 1] [-1 0 0] >>> Q1(M) == Q3 True
sage: Q = DiagonalQuadraticForm(ZZ, [1, -1]) sage: Q.is_globally_equivalent_to(Q) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: not a definite form in QuadraticForm.is_globally_equivalent_to()
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1), -Integer(1)]) >>> Q.is_globally_equivalent_to(Q) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: not a definite form in QuadraticForm.is_globally_equivalent_to()
ALGORITHM: this uses the PARI function pari:qfisom, implementing an algorithm by Plesken and Souvignier.
- is_hyperbolic(p)[source]¶
Check if the quadratic form is a sum of hyperbolic planes over the \(p\)-adic numbers \(\QQ_p\) or over the real numbers \(\RR\).
REFERENCES:
This criterion follows from Cassels’s “Rational Quadratic Forms”:
local invariants for hyperbolic plane (Lemma 2.4, p58)
direct sum formulas (Lemma 2.3, p58)
INPUT:
p
– a prime number > 0 or \(-1\) for the infinite place
OUTPUT: boolean
EXAMPLES:
sage: # needs sage.libs.pari sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) sage: Q.is_hyperbolic(-1) False sage: Q.is_hyperbolic(2) False sage: Q.is_hyperbolic(3) False sage: Q.is_hyperbolic(5) # Here -1 is a square, so it's true. True sage: Q.is_hyperbolic(7) False sage: Q.is_hyperbolic(13) # Here -1 is a square, so it's true. True
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]) >>> Q.is_hyperbolic(-Integer(1)) False >>> Q.is_hyperbolic(Integer(2)) False >>> Q.is_hyperbolic(Integer(3)) False >>> Q.is_hyperbolic(Integer(5)) # Here -1 is a square, so it's true. True >>> Q.is_hyperbolic(Integer(7)) False >>> Q.is_hyperbolic(Integer(13)) # Here -1 is a square, so it's true. True
- is_indefinite()[source]¶
Determines if the given quadratic form is indefinite.
Note
A degenerate form is considered neither definite nor indefinite.
Note
The zero-dimensional form is not considered indefinite.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-3,-5]) sage: Q.is_indefinite() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [-Integer(1),-Integer(3),-Integer(5)]) >>> Q.is_indefinite() False
sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5]) sage: Q.is_indefinite() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(3),Integer(5)]) >>> Q.is_indefinite() True
- is_isotropic(p)[source]¶
Check if \(Q\) is isotropic over the \(p\)-adic numbers \(\QQ_p\) or \(\RR\).
INPUT:
p
– a prime number > 0 or \(-1\) for the infinite place
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1]) sage: Q.is_isotropic(2) # needs sage.libs.pari False sage: Q.is_isotropic(3) # needs sage.libs.pari False sage: Q.is_isotropic(5) # needs sage.libs.pari True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]) >>> Q.is_isotropic(Integer(2)) # needs sage.libs.pari False >>> Q.is_isotropic(Integer(3)) # needs sage.libs.pari False >>> Q.is_isotropic(Integer(5)) # needs sage.libs.pari True
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1]) sage: Q.is_isotropic(2) # needs sage.libs.pari True sage: Q.is_isotropic(3) # needs sage.libs.pari True sage: Q.is_isotropic(5) # needs sage.libs.pari True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(1)]) >>> Q.is_isotropic(Integer(2)) # needs sage.libs.pari True >>> Q.is_isotropic(Integer(3)) # needs sage.libs.pari True >>> Q.is_isotropic(Integer(5)) # needs sage.libs.pari True
sage: [DiagonalQuadraticForm(ZZ, # needs sage.libs.pari ....: [1, -least_quadratic_nonresidue(p)]).is_isotropic(p) ....: for p in prime_range(3, 30)] [False, False, False, False, False, False, False, False, False]
>>> from sage.all import * >>> [DiagonalQuadraticForm(ZZ, # needs sage.libs.pari ... [Integer(1), -least_quadratic_nonresidue(p)]).is_isotropic(p) ... for p in prime_range(Integer(3), Integer(30))] [False, False, False, False, False, False, False, False, False]
sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), # needs sage.libs.pari ....: p, -p*least_quadratic_nonresidue(p)]).is_isotropic(p) ....: for p in prime_range(3, 30)] [False, False, False, False, False, False, False, False, False]
>>> from sage.all import * >>> [DiagonalQuadraticForm(ZZ, [Integer(1), -least_quadratic_nonresidue(p), # needs sage.libs.pari ... p, -p*least_quadratic_nonresidue(p)]).is_isotropic(p) ... for p in prime_range(Integer(3), Integer(30))] [False, False, False, False, False, False, False, False, False]
- is_locally_equivalent_to(other, check_primes_only=False, force_jordan_equivalence_test=False)[source]¶
Determine if the current quadratic form (defined over \(\ZZ\)) is locally equivalent to the given form over the real numbers and the \(p\)-adic integers for every prime \(p\).
This works by comparing the local Jordan decompositions at every prime, and the dimension and signature at the real place.
INPUT:
other
– aQuadraticForm
OUTPUT: boolean
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q2 = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3]) sage: Q1.is_globally_equivalent_to(Q2) # needs sage.libs.pari False sage: Q1.is_locally_equivalent_to(Q2) # needs sage.libs.pari True
>>> from sage.all import * >>> Q1 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q2 = QuadraticForm(ZZ, Integer(3), [Integer(2), Integer(1), Integer(2), Integer(2), Integer(1), Integer(3)]) >>> Q1.is_globally_equivalent_to(Q2) # needs sage.libs.pari False >>> Q1.is_locally_equivalent_to(Q2) # needs sage.libs.pari True
- is_locally_represented_number(m)[source]¶
Determine if the rational number \(m\) is locally represented by the quadratic form.
INPUT:
m
– integer
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.is_locally_represented_number(2) True sage: Q.is_locally_represented_number(7) False sage: Q.is_locally_represented_number(-1) False sage: Q.is_locally_represented_number(28) False sage: Q.is_locally_represented_number(0) True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.is_locally_represented_number(Integer(2)) True >>> Q.is_locally_represented_number(Integer(7)) False >>> Q.is_locally_represented_number(-Integer(1)) False >>> Q.is_locally_represented_number(Integer(28)) False >>> Q.is_locally_represented_number(Integer(0)) True
- is_locally_represented_number_at_place(m, p)[source]¶
Determine if the rational number \(m\) is locally represented by the quadratic form at the (possibly infinite) prime \(p\).
INPUT:
m
– integerp
– a prime number > 0 or ‘infinity’
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.is_locally_represented_number_at_place(7, infinity) True sage: Q.is_locally_represented_number_at_place(7, 2) False sage: Q.is_locally_represented_number_at_place(7, 3) True sage: Q.is_locally_represented_number_at_place(7, 5) True sage: Q.is_locally_represented_number_at_place(-1, infinity) False sage: Q.is_locally_represented_number_at_place(-1, 2) False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.is_locally_represented_number_at_place(Integer(7), infinity) True >>> Q.is_locally_represented_number_at_place(Integer(7), Integer(2)) False >>> Q.is_locally_represented_number_at_place(Integer(7), Integer(3)) True >>> Q.is_locally_represented_number_at_place(Integer(7), Integer(5)) True >>> Q.is_locally_represented_number_at_place(-Integer(1), infinity) False >>> Q.is_locally_represented_number_at_place(-Integer(1), Integer(2)) False
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,-1]) sage: Q.is_locally_represented_number_at_place(7, infinity) # long time (8.5 s) True sage: Q.is_locally_represented_number_at_place(7, 2) # long time True sage: Q.is_locally_represented_number_at_place(7, 3) # long time True sage: Q.is_locally_represented_number_at_place(7, 5) # long time True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1),-Integer(1)]) >>> Q.is_locally_represented_number_at_place(Integer(7), infinity) # long time (8.5 s) True >>> Q.is_locally_represented_number_at_place(Integer(7), Integer(2)) # long time True >>> Q.is_locally_represented_number_at_place(Integer(7), Integer(3)) # long time True >>> Q.is_locally_represented_number_at_place(Integer(7), Integer(5)) # long time True
- is_locally_universal_at_all_places()[source]¶
Determine if the quadratic form represents \(\ZZ_p\) for all finite/non-archimedean primes, and represents all real numbers.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.is_locally_universal_at_all_places() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.is_locally_universal_at_all_places() False
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.is_locally_universal_at_all_places() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.is_locally_universal_at_all_places() False
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,-1]) sage: Q.is_locally_universal_at_all_places() # long time (8.5 s) True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1),-Integer(1)]) >>> Q.is_locally_universal_at_all_places() # long time (8.5 s) True
- is_locally_universal_at_all_primes()[source]¶
Determine if the quadratic form represents \(\ZZ_p\) for all finite/non-archimedean primes.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.is_locally_universal_at_all_primes() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.is_locally_universal_at_all_primes() True
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.is_locally_universal_at_all_primes() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.is_locally_universal_at_all_primes() True
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.is_locally_universal_at_all_primes() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.is_locally_universal_at_all_primes() False
- is_locally_universal_at_prime(p)[source]¶
Determine if the (integer-valued/rational) quadratic form represents all of \(\ZZ_p\).
INPUT:
p
– a positive prime number or “infinity”
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.is_locally_universal_at_prime(2) True sage: Q.is_locally_universal_at_prime(3) True sage: Q.is_locally_universal_at_prime(5) True sage: Q.is_locally_universal_at_prime(infinity) False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.is_locally_universal_at_prime(Integer(2)) True >>> Q.is_locally_universal_at_prime(Integer(3)) True >>> Q.is_locally_universal_at_prime(Integer(5)) True >>> Q.is_locally_universal_at_prime(infinity) False
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.is_locally_universal_at_prime(2) False sage: Q.is_locally_universal_at_prime(3) True sage: Q.is_locally_universal_at_prime(5) True sage: Q.is_locally_universal_at_prime(infinity) False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.is_locally_universal_at_prime(Integer(2)) False >>> Q.is_locally_universal_at_prime(Integer(3)) True >>> Q.is_locally_universal_at_prime(Integer(5)) True >>> Q.is_locally_universal_at_prime(infinity) False
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,-1]) sage: Q.is_locally_universal_at_prime(infinity) True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),-Integer(1)]) >>> Q.is_locally_universal_at_prime(infinity) True
- is_negative_definite()[source]¶
Determines if the given quadratic form is negative-definite.
Note
A degenerate form is considered neither definite nor indefinite.
Note
The zero-dimensional form is considered both positive definite and negative definite.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-3,-5]) sage: Q.is_negative_definite() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [-Integer(1),-Integer(3),-Integer(5)]) >>> Q.is_negative_definite() True
sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5]) sage: Q.is_negative_definite() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(3),Integer(5)]) >>> Q.is_negative_definite() False
- is_odd(allow_rescaling_flag=True)[source]¶
Return true iff after rescaling by some appropriate factor, the form represents some odd integers. For more details, see
parity()
.Requires that \(Q\) is defined over \(\ZZ\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1, 0, 1]) sage: Q.is_odd() True sage: Q = QuadraticForm(ZZ, 2, [1, 1, 1]) sage: Q.is_odd() False
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1), Integer(0), Integer(1)]) >>> Q.is_odd() True >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1), Integer(1), Integer(1)]) >>> Q.is_odd() False
- is_positive_definite()[source]¶
Determines if the given quadratic form is positive-definite.
Note
A degenerate form is considered neither definite nor indefinite.
Note
The zero-dimensional form is considered both positive definite and negative definite.
OUTPUT: boolean
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5]) sage: Q.is_positive_definite() True
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5)]) >>> Q.is_positive_definite() True
sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5]) sage: Q.is_positive_definite() False
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),-Integer(3),Integer(5)]) >>> Q.is_positive_definite() False
- is_primitive()[source]¶
Determine if the given integer-valued form is primitive.
This means not an integer (\(> 1\)) multiple of another integer-valued quadratic form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [2,3,4]) sage: Q.is_primitive() True sage: Q = QuadraticForm(ZZ, 2, [2,4,8]) sage: Q.is_primitive() False
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(2),Integer(3),Integer(4)]) >>> Q.is_primitive() True >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(2),Integer(4),Integer(8)]) >>> Q.is_primitive() False
- is_rationally_isometric(other, return_matrix=False)[source]¶
Determine if two regular quadratic forms over a number field are isometric.
INPUT:
other
– a quadratic form over a number fieldreturn_matrix
– boolean (default:False
); return the transformation matrix instead of a boolean; this is currently only implemented for forms overQQ
OUTPUT:
if
return_matrix
isFalse
: a booleanif
return_matrix
isTrue
: eitherFalse
or the transformation matrix
EXAMPLES:
sage: V = DiagonalQuadraticForm(QQ, [1, 1, 2]) sage: W = DiagonalQuadraticForm(QQ, [2, 2, 2]) sage: V.is_rationally_isometric(W) # needs sage.libs.pari True
>>> from sage.all import * >>> V = DiagonalQuadraticForm(QQ, [Integer(1), Integer(1), Integer(2)]) >>> W = DiagonalQuadraticForm(QQ, [Integer(2), Integer(2), Integer(2)]) >>> V.is_rationally_isometric(W) # needs sage.libs.pari True
sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') sage: K.<a> = NumberField(x^2 - 3) sage: V = QuadraticForm(K, 4, [1, 0, 0, 0, 2*a, 0, 0, a, 0, 2]); V Quadratic form in 4 variables over Number Field in a with defining polynomial x^2 - 3 with coefficients: [ 1 0 0 0 ] [ * 2*a 0 0 ] [ * * a 0 ] [ * * * 2 ] sage: W = QuadraticForm(K, 4, [1, 2*a, 4, 6, 3, 10, 2, 1, 2, 5]); W Quadratic form in 4 variables over Number Field in a with defining polynomial x^2 - 3 with coefficients: [ 1 2*a 4 6 ] [ * 3 10 2 ] [ * * 1 2 ] [ * * * 5 ] sage: V.is_rationally_isometric(W) False
>>> from sage.all import * >>> # needs sage.rings.number_field >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(2) - Integer(3), names=('a',)); (a,) = K._first_ngens(1) >>> V = QuadraticForm(K, Integer(4), [Integer(1), Integer(0), Integer(0), Integer(0), Integer(2)*a, Integer(0), Integer(0), a, Integer(0), Integer(2)]); V Quadratic form in 4 variables over Number Field in a with defining polynomial x^2 - 3 with coefficients: [ 1 0 0 0 ] [ * 2*a 0 0 ] [ * * a 0 ] [ * * * 2 ] >>> W = QuadraticForm(K, Integer(4), [Integer(1), Integer(2)*a, Integer(4), Integer(6), Integer(3), Integer(10), Integer(2), Integer(1), Integer(2), Integer(5)]); W Quadratic form in 4 variables over Number Field in a with defining polynomial x^2 - 3 with coefficients: [ 1 2*a 4 6 ] [ * 3 10 2 ] [ * * 1 2 ] [ * * * 5 ] >>> V.is_rationally_isometric(W) False
sage: # needs sage.rings.number_field sage: K.<a> = NumberField(x^4 + 2*x + 6) sage: V = DiagonalQuadraticForm(K, [a, 2, 3, 2, 1]); V Quadratic form in 5 variables over Number Field in a with defining polynomial x^4 + 2*x + 6 with coefficients: [ a 0 0 0 0 ] [ * 2 0 0 0 ] [ * * 3 0 0 ] [ * * * 2 0 ] [ * * * * 1 ] sage: W = DiagonalQuadraticForm(K, [a, a, a, 2, 1]); W Quadratic form in 5 variables over Number Field in a with defining polynomial x^4 + 2*x + 6 with coefficients: [ a 0 0 0 0 ] [ * a 0 0 0 ] [ * * a 0 0 ] [ * * * 2 0 ] [ * * * * 1 ] sage: V.is_rationally_isometric(W) False
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(4) + Integer(2)*x + Integer(6), names=('a',)); (a,) = K._first_ngens(1) >>> V = DiagonalQuadraticForm(K, [a, Integer(2), Integer(3), Integer(2), Integer(1)]); V Quadratic form in 5 variables over Number Field in a with defining polynomial x^4 + 2*x + 6 with coefficients: [ a 0 0 0 0 ] [ * 2 0 0 0 ] [ * * 3 0 0 ] [ * * * 2 0 ] [ * * * * 1 ] >>> W = DiagonalQuadraticForm(K, [a, a, a, Integer(2), Integer(1)]); W Quadratic form in 5 variables over Number Field in a with defining polynomial x^4 + 2*x + 6 with coefficients: [ a 0 0 0 0 ] [ * a 0 0 0 ] [ * * a 0 0 ] [ * * * 2 0 ] [ * * * * 1 ] >>> V.is_rationally_isometric(W) False
sage: # needs sage.rings.number_field sage: K.<a> = NumberField(x^2 - 3) sage: V = DiagonalQuadraticForm(K, [-1, a, -2*a]) sage: W = DiagonalQuadraticForm(K, [-1, -a, 2*a]) sage: V.is_rationally_isometric(W) True sage: # needs sage.rings.number_field sage: V = DiagonalQuadraticForm(QQ, [1, 1, 2]) sage: W = DiagonalQuadraticForm(QQ, [2, 2, 2]) sage: T = V.is_rationally_isometric(W, True); T [ 0 0 1] [-1/2 -1/2 0] [ 1/2 -1/2 0] sage: V.Gram_matrix() == T.transpose() * W.Gram_matrix() * T True sage: T = W.is_rationally_isometric(V, True); T # needs sage.rings.number_field [ 0 -1 1] [ 0 -1 -1] [ 1 0 0] sage: W.Gram_matrix() == T.T * V.Gram_matrix() * T # needs sage.rings.number_field True
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(2) - Integer(3), names=('a',)); (a,) = K._first_ngens(1) >>> V = DiagonalQuadraticForm(K, [-Integer(1), a, -Integer(2)*a]) >>> W = DiagonalQuadraticForm(K, [-Integer(1), -a, Integer(2)*a]) >>> V.is_rationally_isometric(W) True >>> # needs sage.rings.number_field >>> V = DiagonalQuadraticForm(QQ, [Integer(1), Integer(1), Integer(2)]) >>> W = DiagonalQuadraticForm(QQ, [Integer(2), Integer(2), Integer(2)]) >>> T = V.is_rationally_isometric(W, True); T [ 0 0 1] [-1/2 -1/2 0] [ 1/2 -1/2 0] >>> V.Gram_matrix() == T.transpose() * W.Gram_matrix() * T True >>> T = W.is_rationally_isometric(V, True); T # needs sage.rings.number_field [ 0 -1 1] [ 0 -1 -1] [ 1 0 0] >>> W.Gram_matrix() == T.T * V.Gram_matrix() * T # needs sage.rings.number_field True
sage: L = QuadraticForm(QQ, 3, [2, 2, 0, 2, 2, 5]) sage: M = QuadraticForm(QQ, 3, [2, 2, 0, 3, 2, 3]) sage: L.is_rationally_isometric(M, True) # needs sage.libs.pari False
>>> from sage.all import * >>> L = QuadraticForm(QQ, Integer(3), [Integer(2), Integer(2), Integer(0), Integer(2), Integer(2), Integer(5)]) >>> M = QuadraticForm(QQ, Integer(3), [Integer(2), Integer(2), Integer(0), Integer(3), Integer(2), Integer(3)]) >>> L.is_rationally_isometric(M, True) # needs sage.libs.pari False
sage: A = DiagonalQuadraticForm(QQ, [1, 5]) sage: B = QuadraticForm(QQ, 2, [1, 12, 81]) sage: T = A.is_rationally_isometric(B, True); T # needs sage.libs.pari [ 1 -2] [ 0 1/3] sage: A.Gram_matrix() == T.T * B.Gram_matrix() * T # needs sage.libs.pari True
>>> from sage.all import * >>> A = DiagonalQuadraticForm(QQ, [Integer(1), Integer(5)]) >>> B = QuadraticForm(QQ, Integer(2), [Integer(1), Integer(12), Integer(81)]) >>> T = A.is_rationally_isometric(B, True); T # needs sage.libs.pari [ 1 -2] [ 0 1/3] >>> A.Gram_matrix() == T.T * B.Gram_matrix() * T # needs sage.libs.pari True
sage: C = DiagonalQuadraticForm(QQ, [1, 5, 9]) sage: D = DiagonalQuadraticForm(QQ, [6, 30, 1]) sage: T = C.is_rationally_isometric(D, True); T # needs sage.libs.pari [ 0 -5/6 1/2] [ 0 1/6 1/2] [ -1 0 0] sage: C.Gram_matrix() == T.T * D.Gram_matrix() * T # needs sage.libs.pari True
>>> from sage.all import * >>> C = DiagonalQuadraticForm(QQ, [Integer(1), Integer(5), Integer(9)]) >>> D = DiagonalQuadraticForm(QQ, [Integer(6), Integer(30), Integer(1)]) >>> T = C.is_rationally_isometric(D, True); T # needs sage.libs.pari [ 0 -5/6 1/2] [ 0 1/6 1/2] [ -1 0 0] >>> C.Gram_matrix() == T.T * D.Gram_matrix() * T # needs sage.libs.pari True
sage: E = DiagonalQuadraticForm(QQ, [1, 1]) sage: F = QuadraticForm(QQ, 2, [17, 94, 130]) sage: T = F.is_rationally_isometric(E, True); T # needs sage.libs.pari [ -4 -189/17] [ -1 -43/17] sage: F.Gram_matrix() == T.T * E.Gram_matrix() * T # needs sage.libs.pari True
>>> from sage.all import * >>> E = DiagonalQuadraticForm(QQ, [Integer(1), Integer(1)]) >>> F = QuadraticForm(QQ, Integer(2), [Integer(17), Integer(94), Integer(130)]) >>> T = F.is_rationally_isometric(E, True); T # needs sage.libs.pari [ -4 -189/17] [ -1 -43/17] >>> F.Gram_matrix() == T.T * E.Gram_matrix() * T # needs sage.libs.pari True
- is_zero(v, p=0)[source]¶
Determine if the vector \(v\) is on the conic \(Q(x) = 0\) (mod \(p\)).
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q1.is_zero([0,1,0], 2) True sage: Q1.is_zero([1,1,1], 2) True sage: Q1.is_zero([1,1,0], 2) False
>>> from sage.all import * >>> Q1 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q1.is_zero([Integer(0),Integer(1),Integer(0)], Integer(2)) True >>> Q1.is_zero([Integer(1),Integer(1),Integer(1)], Integer(2)) True >>> Q1.is_zero([Integer(1),Integer(1),Integer(0)], Integer(2)) False
- is_zero_nonsingular(v, p=0)[source]¶
Determine if the vector \(v\) is on the conic \(Q(x) = 0\) (mod \(p\)), and that this point is non-singular point of the conic.
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q1.is_zero_nonsingular([1,1,1], 2) True sage: Q1.is_zero([1, 19, 2], 37) True sage: Q1.is_zero_nonsingular([1, 19, 2], 37) False
>>> from sage.all import * >>> Q1 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q1.is_zero_nonsingular([Integer(1),Integer(1),Integer(1)], Integer(2)) True >>> Q1.is_zero([Integer(1), Integer(19), Integer(2)], Integer(37)) True >>> Q1.is_zero_nonsingular([Integer(1), Integer(19), Integer(2)], Integer(37)) False
- is_zero_singular(v, p=0)[source]¶
Determine if the vector \(v\) is on the conic \(Q(x) = 0\) (mod \(p\)), and that this point is singular point of the conic.
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q1.is_zero([1,1,1], 2) True sage: Q1.is_zero_singular([1,1,1], 2) False sage: Q1.is_zero_singular([1, 19, 2], 37) True
>>> from sage.all import * >>> Q1 = QuadraticForm(ZZ, Integer(3), [Integer(1), Integer(0), -Integer(1), Integer(2), -Integer(1), Integer(5)]) >>> Q1.is_zero([Integer(1),Integer(1),Integer(1)], Integer(2)) True >>> Q1.is_zero_singular([Integer(1),Integer(1),Integer(1)], Integer(2)) False >>> Q1.is_zero_singular([Integer(1), Integer(19), Integer(2)], Integer(37)) True
- jordan_blocks_by_scale_and_unimodular(p, safe_flag=True)[source]¶
Return a list of pairs \((s_i, L_i)\) where \(L_i\) is a maximal \(p^{s_i}\)-unimodular Jordan component which is further decomposed into block diagonals of block size \(\le 2\).
For each \(L_i\) the \(2 \times 2\) blocks are listed after the \(1 \times 1\) blocks (which follows from the convention of the
local_normal_form()
method).Note
The decomposition of each \(L_i\) into smaller blocks is not unique!
The
safe_flag
argument allows us to select whether we want a copy of the output, or the original output. By defaultsafe_flag = True
, so we return a copy of the cached information. If this is set toFalse
, then the routine is much faster but the return values are vulnerable to being corrupted by the user.INPUT:
p
– a prime number > 0
OUTPUT:
A list of pairs \((s_i, L_i)\) where:
\(s_i\) is an integer,
\(L_i\) is a block-diagonal unimodular quadratic form over \(\ZZ_p\).
Note
These forms \(L_i\) are defined over the \(p\)-adic integers, but by a matrix over \(\ZZ\) (or \(\QQ\)?).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,9,5,7]) sage: Q.jordan_blocks_by_scale_and_unimodular(3) [(0, Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 0 ] [ * 5 0 ] [ * * 7 ]), (2, Quadratic form in 1 variables over Integer Ring with coefficients: [ 1 ])]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(9),Integer(5),Integer(7)]) >>> Q.jordan_blocks_by_scale_and_unimodular(Integer(3)) [(0, Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 0 ] [ * 5 0 ] [ * * 7 ]), (2, Quadratic form in 1 variables over Integer Ring with coefficients: [ 1 ])]
sage: Q2 = QuadraticForm(ZZ, 2, [1,1,1]) sage: Q2.jordan_blocks_by_scale_and_unimodular(2) [(-1, Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 2 ] [ * 2 ])] sage: Q = Q2 + Q2.scale_by_factor(2) sage: Q.jordan_blocks_by_scale_and_unimodular(2) [(-1, Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 2 ] [ * 2 ]), (0, Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 2 ] [ * 2 ])]
>>> from sage.all import * >>> Q2 = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(1),Integer(1)]) >>> Q2.jordan_blocks_by_scale_and_unimodular(Integer(2)) [(-1, Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 2 ] [ * 2 ])] >>> Q = Q2 + Q2.scale_by_factor(Integer(2)) >>> Q.jordan_blocks_by_scale_and_unimodular(Integer(2)) [(-1, Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 2 ] [ * 2 ]), (0, Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 2 ] [ * 2 ])]
- jordan_blocks_in_unimodular_list_by_scale_power(p)[source]¶
Return a list of Jordan components, whose component at index \(i\) should be scaled by the factor \(p^i\).
This is only defined for integer-valued quadratic forms (i.e., forms with base ring \(\ZZ\)), and the indexing only works correctly for \(p=2\) when the form has an integer Gram matrix.
INPUT:
self
– a quadratic form over \(\ZZ\), which has integer Gram matrix if \(p = 2\)p
– a prime number > 0
OUTPUT: list of \(p\)-unimodular quadratic forms
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [2, -2, 0, 3, -5, 4]) sage: Q.jordan_blocks_in_unimodular_list_by_scale_power(2) Traceback (most recent call last): ... TypeError: the given quadratic form has a Jordan component with a negative scale exponent sage: Q.scale_by_factor(2).jordan_blocks_in_unimodular_list_by_scale_power(2) [Quadratic form in 2 variables over Integer Ring with coefficients: [ 0 2 ] [ * 0 ], Quadratic form in 0 variables over Integer Ring with coefficients: , Quadratic form in 1 variables over Integer Ring with coefficients: [ 345 ]] sage: Q.jordan_blocks_in_unimodular_list_by_scale_power(3) [Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 0 ] [ * 10 ], Quadratic form in 1 variables over Integer Ring with coefficients: [ 2 ]]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), [Integer(2), -Integer(2), Integer(0), Integer(3), -Integer(5), Integer(4)]) >>> Q.jordan_blocks_in_unimodular_list_by_scale_power(Integer(2)) Traceback (most recent call last): ... TypeError: the given quadratic form has a Jordan component with a negative scale exponent >>> Q.scale_by_factor(Integer(2)).jordan_blocks_in_unimodular_list_by_scale_power(Integer(2)) [Quadratic form in 2 variables over Integer Ring with coefficients: [ 0 2 ] [ * 0 ], Quadratic form in 0 variables over Integer Ring with coefficients: , Quadratic form in 1 variables over Integer Ring with coefficients: [ 345 ]] >>> Q.jordan_blocks_in_unimodular_list_by_scale_power(Integer(3)) [Quadratic form in 2 variables over Integer Ring with coefficients: [ 2 0 ] [ * 10 ], Quadratic form in 1 variables over Integer Ring with coefficients: [ 2 ]]
- level()[source]¶
Determines the level of the quadratic form over a PID, which is a generator for the smallest ideal \(N\) of \(R\) such that \(N\cdot (\) the matrix of \(2*Q\) \()^{(-1)}\) is in \(R\) with diagonal in \(2R\).
Over \(\ZZ\) this returns a nonnegative number.
(Caveat: This always returns the unit ideal when working over a field!)
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, range(1,4)) sage: Q.level() 8 sage: Q1 = QuadraticForm(QQ, 2, range(1,4)) sage: Q1.level() # random UserWarning: Warning -- The level of a quadratic form over a field is always 1. Do you really want to do this?!? 1 sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.level() 420
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), range(Integer(1),Integer(4))) >>> Q.level() 8 >>> Q1 = QuadraticForm(QQ, Integer(2), range(Integer(1),Integer(4))) >>> Q1.level() # random UserWarning: Warning -- The level of a quadratic form over a field is always 1. Do you really want to do this?!? 1 >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.level() 420
- level__Tornaria()[source]¶
Return the level of the quadratic form.
This is defined as
level(\(B\)) for even dimension,
level(\(B\))/4 for odd dimension,
where \(2Q(x) = x^t\cdot B\cdot x\).
This agrees with the usual level for even dimension.
EXAMPLES:
sage: DiagonalQuadraticForm(ZZ, [1]).level__Tornaria() 1 sage: DiagonalQuadraticForm(ZZ, [1,1]).level__Tornaria() 4 sage: DiagonalQuadraticForm(ZZ, [1,1,1]).level__Tornaria() 1 sage: DiagonalQuadraticForm(ZZ, [1,1,1,1]).level__Tornaria() 4
>>> from sage.all import * >>> DiagonalQuadraticForm(ZZ, [Integer(1)]).level__Tornaria() 1 >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]).level__Tornaria() 4 >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]).level__Tornaria() 1 >>> DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]).level__Tornaria() 4
- level_ideal()[source]¶
Determine the level of the quadratic form (over \(R\)), which is the smallest ideal \(N\) of \(R\) such that \(N \cdot (\) the matrix of \(2Q\) \()^{(-1)}\) is in \(R\) with diagonal in \(2R\). (Caveat: This always returns the principal ideal when working over a field!)
Warning
This only works over a PID ring of integers for now! (Waiting for Sage fractional ideal support.)
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, range(1,4)) sage: Q.level_ideal() Principal ideal (8) of Integer Ring sage: Q1 = QuadraticForm(QQ, 2, range(1,4)) sage: Q1.level_ideal() Principal ideal (1) of Rational Field sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.level_ideal() Principal ideal (420) of Integer Ring
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), range(Integer(1),Integer(4))) >>> Q.level_ideal() Principal ideal (8) of Integer Ring >>> Q1 = QuadraticForm(QQ, Integer(2), range(Integer(1),Integer(4))) >>> Q1.level_ideal() Principal ideal (1) of Rational Field >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q.level_ideal() Principal ideal (420) of Integer Ring
- list_external_initializations()[source]¶
Return a list of the fields which were set externally at creation, and not created through the usual
QuadraticForm
methods. These fields are as good as the external process that made them, and are thus not guaranteed to be correct.EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,0,5]) sage: Q.list_external_initializations() [] sage: # needs sage.libs.pari sage: T = Q.theta_series() sage: Q.list_external_initializations() [] sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=False, ....: number_of_automorphisms=3, determinant=0) sage: Q.list_external_initializations() []
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(0),Integer(5)]) >>> Q.list_external_initializations() [] >>> # needs sage.libs.pari >>> T = Q.theta_series() >>> Q.list_external_initializations() [] >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(0),Integer(5)], unsafe_initialization=False, ... number_of_automorphisms=Integer(3), determinant=Integer(0)) >>> Q.list_external_initializations() []
sage: # needs sage.libs.pari sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=False, ....: number_of_automorphisms=3, determinant=0) sage: Q.list_external_initializations() [] sage: Q = QuadraticForm(ZZ, 2, [1,0,5], unsafe_initialization=True, ....: number_of_automorphisms=3, determinant=0) sage: Q.list_external_initializations() ['number_of_automorphisms', 'determinant']
>>> from sage.all import * >>> # needs sage.libs.pari >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(0),Integer(5)], unsafe_initialization=False, ... number_of_automorphisms=Integer(3), determinant=Integer(0)) >>> Q.list_external_initializations() [] >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(1),Integer(0),Integer(5)], unsafe_initialization=True, ... number_of_automorphisms=Integer(3), determinant=Integer(0)) >>> Q.list_external_initializations() ['number_of_automorphisms', 'determinant']
- lll()[source]¶
Return an LLL-reduced form of \(Q\) (using PARI).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(1,11)) sage: Q.is_definite() True sage: Q.lll() # needs sage.libs.pari Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 1 0 ] [ * 4 3 3 ] [ * * 6 3 ] [ * * * 6 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(1),Integer(11))) >>> Q.is_definite() True >>> Q.lll() # needs sage.libs.pari Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 0 1 0 ] [ * 4 3 3 ] [ * * 6 3 ] [ * * * 6 ]
- local_badII_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the Bad-type II local density of \(Q\) representing \(m\) at \(p\). (Assuming that \(p > 2\) and \(Q\) is given in local diagonal form.)
INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_badII_density_congruence(2, 1, None, None) 0 sage: Q.local_badII_density_congruence(2, 2, None, None) 0 sage: Q.local_badII_density_congruence(2, 4, None, None) 0 sage: Q.local_badII_density_congruence(3, 1, None, None) 0 sage: Q.local_badII_density_congruence(3, 6, None, None) 0 sage: Q.local_badII_density_congruence(3, 9, None, None) 0 sage: Q.local_badII_density_congruence(3, 27, None, None) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_badII_density_congruence(Integer(2), Integer(1), None, None) 0 >>> Q.local_badII_density_congruence(Integer(2), Integer(2), None, None) 0 >>> Q.local_badII_density_congruence(Integer(2), Integer(4), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(1), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(9), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(27), None, None) 0
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,3,9,9]) sage: Q.local_badII_density_congruence(3, 1, None, None) 0 sage: Q.local_badII_density_congruence(3, 3, None, None) 0 sage: Q.local_badII_density_congruence(3, 6, None, None) 0 sage: Q.local_badII_density_congruence(3, 9, None, None) 4/27 sage: Q.local_badII_density_congruence(3, 18, None, None) 4/9
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(3),Integer(9),Integer(9)]) >>> Q.local_badII_density_congruence(Integer(3), Integer(1), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(3), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_badII_density_congruence(Integer(3), Integer(9), None, None) 4/27 >>> Q.local_badII_density_congruence(Integer(3), Integer(18), None, None) 4/9
- local_badI_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the Bad-type I local density of \(Q\) representing \(m\) at \(p\). (Assuming that \(p > 2\) and \(Q\) is given in local diagonal form.)
INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_badI_density_congruence(2, 1, None, None) 0 sage: Q.local_badI_density_congruence(2, 2, None, None) 1 sage: Q.local_badI_density_congruence(2, 4, None, None) 0 sage: Q.local_badI_density_congruence(3, 1, None, None) 0 sage: Q.local_badI_density_congruence(3, 6, None, None) 0 sage: Q.local_badI_density_congruence(3, 9, None, None) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_badI_density_congruence(Integer(2), Integer(1), None, None) 0 >>> Q.local_badI_density_congruence(Integer(2), Integer(2), None, None) 1 >>> Q.local_badI_density_congruence(Integer(2), Integer(4), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(1), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(9), None, None) 0
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_badI_density_congruence(2, 1, None, None) 0 sage: Q.local_badI_density_congruence(2, 2, None, None) 0 sage: Q.local_badI_density_congruence(2, 4, None, None) 0 sage: Q.local_badI_density_congruence(3, 2, None, None) 0 sage: Q.local_badI_density_congruence(3, 6, None, None) 0 sage: Q.local_badI_density_congruence(3, 9, None, None) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_badI_density_congruence(Integer(2), Integer(1), None, None) 0 >>> Q.local_badI_density_congruence(Integer(2), Integer(2), None, None) 0 >>> Q.local_badI_density_congruence(Integer(2), Integer(4), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(2), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(9), None, None) 0
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,3,9]) sage: Q.local_badI_density_congruence(3, 1, None, None) 0 sage: Q.local_badI_density_congruence(3, 3, None, None) 4/3 sage: Q.local_badI_density_congruence(3, 6, None, None) 4/3 sage: Q.local_badI_density_congruence(3, 9, None, None) 0 sage: Q.local_badI_density_congruence(3, 18, None, None) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(3),Integer(9)]) >>> Q.local_badI_density_congruence(Integer(3), Integer(1), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(3), None, None) 4/3 >>> Q.local_badI_density_congruence(Integer(3), Integer(6), None, None) 4/3 >>> Q.local_badI_density_congruence(Integer(3), Integer(9), None, None) 0 >>> Q.local_badI_density_congruence(Integer(3), Integer(18), None, None) 0
- local_bad_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the Bad-type local density of \(Q\) representing \(m\) at \(p\), allowing certain congruence conditions mod \(p\).
INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_bad_density_congruence(2, 1, None, None) 0 sage: Q.local_bad_density_congruence(2, 2, None, None) 1 sage: Q.local_bad_density_congruence(2, 4, None, None) 0 sage: Q.local_bad_density_congruence(3, 1, None, None) 0 sage: Q.local_bad_density_congruence(3, 6, None, None) 0 sage: Q.local_bad_density_congruence(3, 9, None, None) 0 sage: Q.local_bad_density_congruence(3, 27, None, None) 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_bad_density_congruence(Integer(2), Integer(1), None, None) 0 >>> Q.local_bad_density_congruence(Integer(2), Integer(2), None, None) 1 >>> Q.local_bad_density_congruence(Integer(2), Integer(4), None, None) 0 >>> Q.local_bad_density_congruence(Integer(3), Integer(1), None, None) 0 >>> Q.local_bad_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_bad_density_congruence(Integer(3), Integer(9), None, None) 0 >>> Q.local_bad_density_congruence(Integer(3), Integer(27), None, None) 0
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,3,9,9]) sage: Q.local_bad_density_congruence(3, 1, None, None) 0 sage: Q.local_bad_density_congruence(3, 3, None, None) 4/3 sage: Q.local_bad_density_congruence(3, 6, None, None) 4/3 sage: Q.local_bad_density_congruence(3, 9, None, None) 4/27 sage: Q.local_bad_density_congruence(3, 18, None, None) 4/9 sage: Q.local_bad_density_congruence(3, 27, None, None) 8/27
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(3),Integer(9),Integer(9)]) >>> Q.local_bad_density_congruence(Integer(3), Integer(1), None, None) 0 >>> Q.local_bad_density_congruence(Integer(3), Integer(3), None, None) 4/3 >>> Q.local_bad_density_congruence(Integer(3), Integer(6), None, None) 4/3 >>> Q.local_bad_density_congruence(Integer(3), Integer(9), None, None) 4/27 >>> Q.local_bad_density_congruence(Integer(3), Integer(18), None, None) 4/9 >>> Q.local_bad_density_congruence(Integer(3), Integer(27), None, None) 8/27
- local_density(p, m)[source]¶
Return the local density.
Note
This screens for imprimitive forms, and puts the quadratic form in local normal form, which is a requirement of the routines performing the computations!
INPUT:
p
– a prime number > 0m
– integer
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) # NOTE: This is already in local normal form for *all* primes p! sage: Q.local_density(p=2, m=1) 1 sage: Q.local_density(p=3, m=1) 8/9 sage: Q.local_density(p=5, m=1) 24/25 sage: Q.local_density(p=7, m=1) 48/49 sage: Q.local_density(p=11, m=1) 120/121
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) # NOTE: This is already in local normal form for *all* primes p! >>> Q.local_density(p=Integer(2), m=Integer(1)) 1 >>> Q.local_density(p=Integer(3), m=Integer(1)) 8/9 >>> Q.local_density(p=Integer(5), m=Integer(1)) 24/25 >>> Q.local_density(p=Integer(7), m=Integer(1)) 48/49 >>> Q.local_density(p=Integer(11), m=Integer(1)) 120/121
- local_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the local density of \(Q\) representing \(m\) at \(p\), allowing certain congruence conditions mod \(p\).
INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_density_congruence(p=2, m=1, Zvec=None, NZvec=None) 1 sage: Q.local_density_congruence(p=3, m=1, Zvec=None, NZvec=None) 8/9 sage: Q.local_density_congruence(p=5, m=1, Zvec=None, NZvec=None) 24/25 sage: Q.local_density_congruence(p=7, m=1, Zvec=None, NZvec=None) 48/49 sage: Q.local_density_congruence(p=11, m=1, Zvec=None, NZvec=None) 120/121
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_density_congruence(p=Integer(2), m=Integer(1), Zvec=None, NZvec=None) 1 >>> Q.local_density_congruence(p=Integer(3), m=Integer(1), Zvec=None, NZvec=None) 8/9 >>> Q.local_density_congruence(p=Integer(5), m=Integer(1), Zvec=None, NZvec=None) 24/25 >>> Q.local_density_congruence(p=Integer(7), m=Integer(1), Zvec=None, NZvec=None) 48/49 >>> Q.local_density_congruence(p=Integer(11), m=Integer(1), Zvec=None, NZvec=None) 120/121
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_density_congruence(2, 1, None, None) 1 sage: Q.local_density_congruence(2, 2, None, None) 1 sage: Q.local_density_congruence(2, 4, None, None) 3/2 sage: Q.local_density_congruence(3, 1, None, None) 2/3 sage: Q.local_density_congruence(3, 6, None, None) 4/3 sage: Q.local_density_congruence(3, 9, None, None) 14/9 sage: Q.local_density_congruence(3, 27, None, None) 2
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_density_congruence(Integer(2), Integer(1), None, None) 1 >>> Q.local_density_congruence(Integer(2), Integer(2), None, None) 1 >>> Q.local_density_congruence(Integer(2), Integer(4), None, None) 3/2 >>> Q.local_density_congruence(Integer(3), Integer(1), None, None) 2/3 >>> Q.local_density_congruence(Integer(3), Integer(6), None, None) 4/3 >>> Q.local_density_congruence(Integer(3), Integer(9), None, None) 14/9 >>> Q.local_density_congruence(Integer(3), Integer(27), None, None) 2
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,3,9,9]) sage: Q.local_density_congruence(3, 1, None, None) 2 sage: Q.local_density_congruence(3, 3, None, None) 4/3 sage: Q.local_density_congruence(3, 6, None, None) 4/3 sage: Q.local_density_congruence(3, 9, None, None) 2/9 sage: Q.local_density_congruence(3, 18, None, None) 4/9
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(3),Integer(9),Integer(9)]) >>> Q.local_density_congruence(Integer(3), Integer(1), None, None) 2 >>> Q.local_density_congruence(Integer(3), Integer(3), None, None) 4/3 >>> Q.local_density_congruence(Integer(3), Integer(6), None, None) 4/3 >>> Q.local_density_congruence(Integer(3), Integer(9), None, None) 2/9 >>> Q.local_density_congruence(Integer(3), Integer(18), None, None) 4/9
- local_genus_symbol(p)[source]¶
Return the Conway-Sloane genus symbol of 2 times a quadratic form defined over \(\ZZ\) at a prime number \(p\).
This is defined (in the class
Genus_Symbol_p_adic_ring
) to be a list of tuples (one for each Jordan component \(p^m\cdot A\) at \(p\), where \(A\) is a unimodular symmetric matrix with coefficients the \(p\)-adic integers) of the following form:If \(p>2\), then return triples of the form [\(m\), \(n\), \(d\)] where
\(m\) = valuation of the component
\(n\) = rank of \(A\)
\(d\) = det(\(A\)) in {1, \(u\)} for normalized quadratic non-residue \(u\).
If \(p=2\), then return quintuples of the form [\(m\), \(n\), \(s\), \(d\), \(o\)] where
\(m\) = valuation of the component
\(n\) = rank of \(A\)
\(d\) = det(\(A\)) in {1, 3, 5, 7}
\(s\) = 0 (or 1) if \(A\) is even (or odd)
\(o\) = oddity of \(A\) (= 0 if \(s\) = 0) in \(\ZZ/8\ZZ\) = the trace of the diagonalization of \(A\)
Note
The Conway-Sloane convention for describing the prime \(p = -1\) is not supported here, and neither is the convention for including the ‘prime’ Infinity. See note on p370 of Conway-Sloane (3rd ed) [CS1999] for a discussion of this convention.
INPUT:
p
– a prime number > 0
OUTPUT:
a Conway-Sloane genus symbol at \(p\), which is an instance of the class
Genus_Symbol_p_adic_ring
.EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3,4]) sage: Q.local_genus_symbol(2) Genus symbol at 2: [2^-2 4^1 8^1]_6 sage: Q.local_genus_symbol(3) Genus symbol at 3: 1^3 3^-1 sage: Q.local_genus_symbol(5) Genus symbol at 5: 1^4
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3),Integer(4)]) >>> Q.local_genus_symbol(Integer(2)) Genus symbol at 2: [2^-2 4^1 8^1]_6 >>> Q.local_genus_symbol(Integer(3)) Genus symbol at 3: 1^3 3^-1 >>> Q.local_genus_symbol(Integer(5)) Genus symbol at 5: 1^4
- local_good_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the Good-type local density of \(Q\) representing \(m\) at \(p\). (Front end routine for parity specific routines for \(p\).)
Todo
Add documentation about the additional congruence conditions
Zvec
andNZvec
.INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_good_density_congruence(2, 1, None, None) 1 sage: Q.local_good_density_congruence(3, 1, None, None) 2/3
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_good_density_congruence(Integer(2), Integer(1), None, None) 1 >>> Q.local_good_density_congruence(Integer(3), Integer(1), None, None) 2/3
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_good_density_congruence(2, 1, None, None) 1 sage: Q.local_good_density_congruence(3, 1, None, None) 8/9
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_good_density_congruence(Integer(2), Integer(1), None, None) 1 >>> Q.local_good_density_congruence(Integer(3), Integer(1), None, None) 8/9
- local_good_density_congruence_even(m, Zvec, NZvec)[source]¶
Find the Good-type local density of \(Q\) representing \(m\) at \(p=2\). (Assuming \(Q\) is given in local diagonal form.)
The additional congruence condition arguments
Zvec
andNZvec
can be either a list of indices or None.Zvec=[]
is equivalent toZvec=None
which both impose no additional conditions, butNZvec=[]
returns no solutions always whileNZvec=None
imposes no additional condition.Warning
Here the indices passed in
Zvec
andNZvec
represent indices of the solution vector \(x\) of \(Q(x) = m\) (mod \(p^k\)), and not the Jordan components of \(Q\). They therefore are required (and assumed) to include either all or none of the indices of a given Jordan component of \(Q\). This is only important when \(p=2\) since otherwise all Jordan blocks are \(1 \times 1\), and so there the indices and Jordan blocks coincide.Todo
Add type checking for
Zvec
andNZvec
, and that \(Q\) is in local normal form.INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and 2-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_good_density_congruence_even(1, None, None) 1
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_good_density_congruence_even(Integer(1), None, None) 1
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_good_density_congruence_even(1, None, None) 1 sage: Q.local_good_density_congruence_even(2, None, None) 3/2 sage: Q.local_good_density_congruence_even(3, None, None) 1 sage: Q.local_good_density_congruence_even(4, None, None) 1/2
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_good_density_congruence_even(Integer(1), None, None) 1 >>> Q.local_good_density_congruence_even(Integer(2), None, None) 3/2 >>> Q.local_good_density_congruence_even(Integer(3), None, None) 1 >>> Q.local_good_density_congruence_even(Integer(4), None, None) 1/2
sage: Q = QuadraticForm(ZZ, 4, range(10)) sage: Q[0,0] = 5 sage: Q[1,1] = 10 sage: Q[2,2] = 15 sage: Q[3,3] = 20 sage: Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 5 1 2 3 ] [ * 10 5 6 ] [ * * 15 8 ] [ * * * 20 ] sage: Q.theta_series(20) # needs sage.libs.pari 1 + 2*q^5 + 2*q^10 + 2*q^14 + 2*q^15 + 2*q^16 + 2*q^18 + O(q^20) sage: Q_local = Q.local_normal_form(2) # needs sage.libs.pari sage.rings.padics sage: Q_local.local_good_density_congruence_even(1, None, None) # needs sage.libs.pari sage.rings.padics 3/4 sage: Q_local.local_good_density_congruence_even(2, None, None) # needs sage.libs.pari sage.rings.padics 9/8 sage: Q_local.local_good_density_congruence_even(5, None, None) # needs sage.libs.pari sage.rings.padics 3/4
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(10))) >>> Q[Integer(0),Integer(0)] = Integer(5) >>> Q[Integer(1),Integer(1)] = Integer(10) >>> Q[Integer(2),Integer(2)] = Integer(15) >>> Q[Integer(3),Integer(3)] = Integer(20) >>> Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 5 1 2 3 ] [ * 10 5 6 ] [ * * 15 8 ] [ * * * 20 ] >>> Q.theta_series(Integer(20)) # needs sage.libs.pari 1 + 2*q^5 + 2*q^10 + 2*q^14 + 2*q^15 + 2*q^16 + 2*q^18 + O(q^20) >>> Q_local = Q.local_normal_form(Integer(2)) # needs sage.libs.pari sage.rings.padics >>> Q_local.local_good_density_congruence_even(Integer(1), None, None) # needs sage.libs.pari sage.rings.padics 3/4 >>> Q_local.local_good_density_congruence_even(Integer(2), None, None) # needs sage.libs.pari sage.rings.padics 9/8 >>> Q_local.local_good_density_congruence_even(Integer(5), None, None) # needs sage.libs.pari sage.rings.padics 3/4
- local_good_density_congruence_odd(p, m, Zvec, NZvec)[source]¶
Find the Good-type local density of \(Q\) representing \(m\) at \(p\). (Assuming that \(p > 2\) and \(Q\) is given in local diagonal form.)
The additional congruence condition arguments
Zvec
andNZvec
can be either a list of indices or None.Zvec=[]
is equivalent toZvec=None
, which both impose no additional conditions, butNZvec=[]
returns no solutions always whileNZvec=None
imposes no additional condition.Todo
Add type checking for
Zvec
,NZvec
, and that \(Q\) is in local normal form.INPUT:
self
– quadratic form \(Q\), assumed to be diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_good_density_congruence_odd(3, 1, None, None) 2/3
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_good_density_congruence_odd(Integer(3), Integer(1), None, None) 2/3
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_good_density_congruence_odd(3, 1, None, None) 8/9
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_good_density_congruence_odd(Integer(3), Integer(1), None, None) 8/9
- local_normal_form(p)[source]¶
Return a locally integrally equivalent quadratic form over the \(p\)-adic integers \(\ZZ_p\) which gives the Jordan decomposition.
The Jordan components are written as sums of blocks of size \(\leq 2\) and are arranged by increasing scale, and then by increasing norm. This is equivalent to saying that we put the \(1 \times 1\) blocks before the \(2 \times 2\) blocks in each Jordan component.
INPUT:
p
– a positive prime number
OUTPUT: a quadratic form over \(\ZZ\)
Warning
Currently this only works for quadratic forms defined over \(\ZZ\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [10,4,1]) sage: Q.local_normal_form(5) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 6 ]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(2), [Integer(10),Integer(4),Integer(1)]) >>> Q.local_normal_form(Integer(5)) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 6 ]
sage: Q.local_normal_form(3) Quadratic form in 2 variables over Integer Ring with coefficients: [ 10 0 ] [ * 15 ] sage: Q.local_normal_form(2) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 6 ]
>>> from sage.all import * >>> Q.local_normal_form(Integer(3)) Quadratic form in 2 variables over Integer Ring with coefficients: [ 10 0 ] [ * 15 ] >>> Q.local_normal_form(Integer(2)) Quadratic form in 2 variables over Integer Ring with coefficients: [ 1 0 ] [ * 6 ]
- local_primitive_density(p, m)[source]¶
Return the local primitive density – should be called by the user.
NOTE: This screens for imprimitive forms, and puts the quadratic form in local normal form, which is a requirement of the routines performing the computations!
INPUT:
p
– a prime number > 0m
– integer
OUTPUT: a rational number
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(10)) sage: Q[0,0] = 5 sage: Q[1,1] = 10 sage: Q[2,2] = 15 sage: Q[3,3] = 20 sage: Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 5 1 2 3 ] [ * 10 5 6 ] [ * * 15 8 ] [ * * * 20 ] sage: Q.theta_series(20) # needs sage.libs.pari 1 + 2*q^5 + 2*q^10 + 2*q^14 + 2*q^15 + 2*q^16 + 2*q^18 + O(q^20) sage: Q.local_normal_form(2) Quadratic form in 4 variables over Integer Ring with coefficients: [ 0 1 0 0 ] [ * 0 0 0 ] [ * * 0 1 ] [ * * * 0 ] sage: Q.local_primitive_density(2, 1) 3/4 sage: Q.local_primitive_density(5, 1) 24/25 sage: Q.local_primitive_density(2, 5) 3/4 sage: Q.local_density(2, 5) 3/4
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), range(Integer(10))) >>> Q[Integer(0),Integer(0)] = Integer(5) >>> Q[Integer(1),Integer(1)] = Integer(10) >>> Q[Integer(2),Integer(2)] = Integer(15) >>> Q[Integer(3),Integer(3)] = Integer(20) >>> Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 5 1 2 3 ] [ * 10 5 6 ] [ * * 15 8 ] [ * * * 20 ] >>> Q.theta_series(Integer(20)) # needs sage.libs.pari 1 + 2*q^5 + 2*q^10 + 2*q^14 + 2*q^15 + 2*q^16 + 2*q^18 + O(q^20) >>> Q.local_normal_form(Integer(2)) Quadratic form in 4 variables over Integer Ring with coefficients: [ 0 1 0 0 ] [ * 0 0 0 ] [ * * 0 1 ] [ * * * 0 ] >>> Q.local_primitive_density(Integer(2), Integer(1)) 3/4 >>> Q.local_primitive_density(Integer(5), Integer(1)) 24/25 >>> Q.local_primitive_density(Integer(2), Integer(5)) 3/4 >>> Q.local_density(Integer(2), Integer(5)) 3/4
- local_primitive_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the primitive local density of \(Q\) representing \(m\) at \(p\), allowing certain congruence conditions mod \(p\).
Note
The following routine is not used internally, but is included for consistency.
INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_primitive_density_congruence(p=2, m=1, Zvec=None, NZvec=None) 1 sage: Q.local_primitive_density_congruence(p=3, m=1, Zvec=None, NZvec=None) 8/9 sage: Q.local_primitive_density_congruence(p=5, m=1, Zvec=None, NZvec=None) 24/25 sage: Q.local_primitive_density_congruence(p=7, m=1, Zvec=None, NZvec=None) 48/49 sage: Q.local_primitive_density_congruence(p=11, m=1, Zvec=None, NZvec=None) 120/121
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_primitive_density_congruence(p=Integer(2), m=Integer(1), Zvec=None, NZvec=None) 1 >>> Q.local_primitive_density_congruence(p=Integer(3), m=Integer(1), Zvec=None, NZvec=None) 8/9 >>> Q.local_primitive_density_congruence(p=Integer(5), m=Integer(1), Zvec=None, NZvec=None) 24/25 >>> Q.local_primitive_density_congruence(p=Integer(7), m=Integer(1), Zvec=None, NZvec=None) 48/49 >>> Q.local_primitive_density_congruence(p=Integer(11), m=Integer(1), Zvec=None, NZvec=None) 120/121
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_primitive_density_congruence(2, 1, None, None) 1 sage: Q.local_primitive_density_congruence(2, 2, None, None) 1 sage: Q.local_primitive_density_congruence(2, 4, None, None) 1 sage: Q.local_primitive_density_congruence(3, 1, None, None) 2/3 sage: Q.local_primitive_density_congruence(3, 6, None, None) 4/3 sage: Q.local_primitive_density_congruence(3, 9, None, None) 4/3 sage: Q.local_primitive_density_congruence(3, 27, None, None) 4/3
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_primitive_density_congruence(Integer(2), Integer(1), None, None) 1 >>> Q.local_primitive_density_congruence(Integer(2), Integer(2), None, None) 1 >>> Q.local_primitive_density_congruence(Integer(2), Integer(4), None, None) 1 >>> Q.local_primitive_density_congruence(Integer(3), Integer(1), None, None) 2/3 >>> Q.local_primitive_density_congruence(Integer(3), Integer(6), None, None) 4/3 >>> Q.local_primitive_density_congruence(Integer(3), Integer(9), None, None) 4/3 >>> Q.local_primitive_density_congruence(Integer(3), Integer(27), None, None) 4/3
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,3,9,9]) sage: Q.local_primitive_density_congruence(3, 1, None, None) 2 sage: Q.local_primitive_density_congruence(3, 3, None, None) 4/3 sage: Q.local_primitive_density_congruence(3, 6, None, None) 4/3 sage: Q.local_primitive_density_congruence(3, 9, None, None) 4/27 sage: Q.local_primitive_density_congruence(3, 18, None, None) 4/9 sage: Q.local_primitive_density_congruence(3, 27, None, None) 8/27 sage: Q.local_primitive_density_congruence(3, 81, None, None) 8/27 sage: Q.local_primitive_density_congruence(3, 243, None, None) 8/27
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(3),Integer(9),Integer(9)]) >>> Q.local_primitive_density_congruence(Integer(3), Integer(1), None, None) 2 >>> Q.local_primitive_density_congruence(Integer(3), Integer(3), None, None) 4/3 >>> Q.local_primitive_density_congruence(Integer(3), Integer(6), None, None) 4/3 >>> Q.local_primitive_density_congruence(Integer(3), Integer(9), None, None) 4/27 >>> Q.local_primitive_density_congruence(Integer(3), Integer(18), None, None) 4/9 >>> Q.local_primitive_density_congruence(Integer(3), Integer(27), None, None) 8/27 >>> Q.local_primitive_density_congruence(Integer(3), Integer(81), None, None) 8/27 >>> Q.local_primitive_density_congruence(Integer(3), Integer(243), None, None) 8/27
- local_representation_conditions(recompute_flag=False, silent_flag=False)[source]¶
Warning
This only works correctly for forms in >=3 variables, which are locally universal at almost all primes!
This class finds the local conditions for a number to be integrally represented by an integer-valued quadratic form. These conditions are stored in
self.__local_representability_conditions
and consist of a list of 9 element vectors, with one for each prime with a local obstruction (though only the first 5 are meaningful unless \(p=2\)). The first element is always the prime \(p\) where the local obstruction occurs, and the next 8 (or 4) entries represent square-classes in the \(p\)-adic integers \(\ZZ_p\), and are labeled by the \(\QQ_p\) square-classes \(t\cdot (\QQ_p)^2\) with \(t\) given as follows:for \(p > 2\),
[ * 1 u p u p * * * * ]
,for \(p = 2\),
[ * 1 3 5 7 2 6 10 14 ]
.
The integer appearing in each place tells us how \(p\)-divisible a number needs to be in that square-class in order to be locally represented by \(Q\). A negative number indicates that the entire \(\QQ_p\) square-class is not represented, while a positive number \(x\) indicates that \(t\cdot p^{(2\cdot x)} (\ZZ_p)^2\) is locally represented but \(t\cdot p^{(2\cdot (x-1))}\) \((\ZZ_p)^2\) is not.
As an example, the vector
[2 3 0 0 0 0 2 0 infinity]
tells us that all positive integers are locally represented at \(p=2\) except those of the forms:\(2^6\cdot u\cdot r^2\) with \(u = 1\) (mod 8)
\(2^5\cdot u\cdot r^2\) with \(u = 3\) (mod 8)
\(2\cdot u\cdot r^2\) with \(u = 7\) (mod 8)
At the real numbers, the vector which looks like
[infinity, 0, infinity, None, None, None, None, None, None]
means that \(Q\) is negative definite (i.e., the 0 tells us all positive reals are represented). The real vector always appears, and is listed before the other ones.OUTPUT:
A list of 9-element vectors describing the representation obstructions at primes dividing the level.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, []) sage: Q.local_representation_conditions() This 0-dimensional form only represents zero. sage: Q = DiagonalQuadraticForm(ZZ, [5]) sage: Q.local_representation_conditions() This 1-dimensional form only represents square multiples of 5. sage: Q1 = DiagonalQuadraticForm(ZZ, [1,1]) sage: Q1.local_representation_conditions() This 2-dimensional form represents the p-adic integers of even valuation for all primes p except [2]. For these and the reals, we have: Reals: [0, +Infinity] p = 2: [0, +Infinity, 0, +Infinity, 0, +Infinity, 0, +Infinity] sage: Q1 = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q1.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except [2]. For these and the reals, we have: Reals: [0, +Infinity] p = 2: [0, 0, 0, +Infinity, 0, 0, 0, 0] sage: Q1 = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q1.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except []. For these and the reals, we have: Reals: [0, +Infinity] sage: Q1 = DiagonalQuadraticForm(ZZ, [1,3,3,3]) sage: Q1.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except [3]. For these and the reals, we have: Reals: [0, +Infinity] p = 3: [0, 1, 0, 0] sage: Q2 = DiagonalQuadraticForm(ZZ, [2,3,3,3]) sage: Q2.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except [3]. For these and the reals, we have: Reals: [0, +Infinity] p = 3: [1, 0, 0, 0] sage: Q3 = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q3.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except []. For these and the reals, we have: Reals: [0, +Infinity]
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, []) >>> Q.local_representation_conditions() This 0-dimensional form only represents zero. >>> Q = DiagonalQuadraticForm(ZZ, [Integer(5)]) >>> Q.local_representation_conditions() This 1-dimensional form only represents square multiples of 5. >>> Q1 = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1)]) >>> Q1.local_representation_conditions() This 2-dimensional form represents the p-adic integers of even valuation for all primes p except [2]. For these and the reals, we have: Reals: [0, +Infinity] p = 2: [0, +Infinity, 0, +Infinity, 0, +Infinity, 0, +Infinity] >>> Q1 = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q1.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except [2]. For these and the reals, we have: Reals: [0, +Infinity] p = 2: [0, 0, 0, +Infinity, 0, 0, 0, 0] >>> Q1 = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q1.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except []. For these and the reals, we have: Reals: [0, +Infinity] >>> Q1 = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(3),Integer(3)]) >>> Q1.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except [3]. For these and the reals, we have: Reals: [0, +Infinity] p = 3: [0, 1, 0, 0] >>> Q2 = DiagonalQuadraticForm(ZZ, [Integer(2),Integer(3),Integer(3),Integer(3)]) >>> Q2.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except [3]. For these and the reals, we have: Reals: [0, +Infinity] p = 3: [1, 0, 0, 0] >>> Q3 = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(3),Integer(5),Integer(7)]) >>> Q3.local_representation_conditions() This form represents the p-adic integers Z_p for all primes p except []. For these and the reals, we have: Reals: [0, +Infinity]
- local_zero_density_congruence(p, m, Zvec=None, NZvec=None)[source]¶
Find the Zero-type local density of \(Q\) representing \(m\) at \(p\), allowing certain congruence conditions mod \(p\).
INPUT:
self
– quadratic form \(Q\), assumed to be block diagonal and \(p\)-integralp
– a prime numberm
– integerZvec
,NZvec
– non-repeating lists of integers inrange(self.dim())
orNone
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3]) sage: Q.local_zero_density_congruence(2, 2, None, None) 0 sage: Q.local_zero_density_congruence(2, 4, None, None) 1/2 sage: Q.local_zero_density_congruence(3, 6, None, None) 0 sage: Q.local_zero_density_congruence(3, 9, None, None) 2/9
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> Q.local_zero_density_congruence(Integer(2), Integer(2), None, None) 0 >>> Q.local_zero_density_congruence(Integer(2), Integer(4), None, None) 1/2 >>> Q.local_zero_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_zero_density_congruence(Integer(3), Integer(9), None, None) 2/9
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.local_zero_density_congruence(2, 2, None, None) 0 sage: Q.local_zero_density_congruence(2, 4, None, None) 1/4 sage: Q.local_zero_density_congruence(3, 6, None, None) 0 sage: Q.local_zero_density_congruence(3, 9, None, None) 8/81
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> Q.local_zero_density_congruence(Integer(2), Integer(2), None, None) 0 >>> Q.local_zero_density_congruence(Integer(2), Integer(4), None, None) 1/4 >>> Q.local_zero_density_congruence(Integer(3), Integer(6), None, None) 0 >>> Q.local_zero_density_congruence(Integer(3), Integer(9), None, None) 8/81
- mass__by_Siegel_densities(odd_algorithm='Pall', even_algorithm='Watson')[source]¶
Return the mass of transformations (det 1 and -1).
Warning
This is broken right now…
INPUT:
odd_algorithm
– algorithm to be used when \(p>2\);'Pall'
(only one choice for now)even_algorithm
– algorithm to be used when \(p=2\); either'Kitaoka'
or'Watson'
(the default)
REFERENCES:
Nipp’s Book “Tables of Quaternary Quadratic Forms”.
Papers of Pall (only for \(p>2\)) and Watson (for \(p=2\) – tricky!).
Siegel, Milnor-Hussemoller, Conway-Sloane Paper IV, Kitoaka (all of which have problems…)
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic 1/384 sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # needs sage.symbolic 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1),Integer(1)]) >>> m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic 1/384 >>> m - (Integer(2)**Q.dim() * factorial(Q.dim()))**(-Integer(1)) # needs sage.symbolic 0
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic 1/48 sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # needs sage.symbolic 0
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic 1/48 >>> m - (Integer(2)**Q.dim() * factorial(Q.dim()))**(-Integer(1)) # needs sage.symbolic 0
- mass_at_two_by_counting_mod_power(k)[source]¶
Compute the local mass at \(p=2\) assuming that it’s stable (mod \(2^k\)).
Note
This is way too slow to be useful, even when \(k=1\).
Todo
Remove this routine, or try to compile it!
INPUT:
k
– integer \(\geq 1\)
OUTPUT: a rational number
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.mass_at_two_by_counting_mod_power(1) 4
>>> from sage.all import * >>> Q = DiagonalQuadraticForm(ZZ, [Integer(1),Integer(1),Integer(1)]) >>> Q.mass_at_two_by_counting_mod_power(Integer(1)) 4
- matrix()[source]¶
Return the Hessian matrix \(A\) for which \(Q(X) = (1/2) X^t\cdot A\cdot X\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, range(6)) sage: Q.matrix() [ 0 1 2] [ 1 6 4] [ 2 4 10]
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(3), range(Integer(6))) >>> Q.matrix() [ 0 1 2] [ 1 6 4] [ 2 4 10]
- minkowski_reduction()[source]¶
Find a Minkowski-reduced form equivalent to the given one.
This means that
\[Q(v_k) \leq Q(s_1\cdot v_1 + ... + s_n\cdot v_n)\]for all \(s_i\) where \(\gcd(s_k, ... s_n) = 1\).
Note
When \(Q\) has dim \(\leq 4\) we can take all \(s_i\) in \(\{1, 0, -1\}\).
REFERENCES:
Schulze-Pillot’s paper on “An algorithm for computing genera of ternary and quaternary quadratic forms”, p138.
Donaldson’s 1979 paper “Minkowski Reduction of Integral Matrices”, p203.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, [30, 17, 11, 12, 29, 25, 62, 64, 25, 110]) sage: Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 12 ] [ * 29 25 62 ] [ * * 64 25 ] [ * * * 110 ] sage: Q.minkowski_reduction() ( Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 -5 ] [ * 29 25 4 ] [ * * 64 0 ] [ * * * 77 ] , [ 1 0 0 0] [ 0 1 0 -1] [ 0 0 1 0] [ 0 0 0 1] )
>>> from sage.all import * >>> Q = QuadraticForm(ZZ, Integer(4), [Integer(30), Integer(17), Integer(11), Integer(12), Integer(29), Integer(25), Integer(62), Integer(64), Integer(25), Integer(110)]) >>> Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 12 ] [ * 29 25 62 ] [ * * 64 25 ] [ * * * 110 ] >>> Q.minkowski_reduction() ( Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 -5 ] [ * 29 25 4 ] [ * * 64 0 ] [ * * * 77 ] , <BLANKLINE> [ 1 0 0 0] [ 0 1 0 -1] [ 0 0 1 0] [ 0 0 0 1] )
sage: Q = QuadraticForm(ZZ,4,[1, -2, 0, 0, 2, 0, 0, 2, 0, 2]) sage: Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 1 -2 0 0 ] [ * 2 0 0 ] [ * * 2 0 ] [ * * * 2 ]