AUTHORS:
Returns a quadratic form over \(R\) which is a sum of squares.
INPUT:
OUTPUT:
quadratic form
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 0 0 0 ]
[ * 3 0 0 ]
[ * * 5 0 ]
[ * * * 7 ]
Bases: sage.structure.sage_object.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.
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:
OUTPUT:
quadratic form
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1,2,3,4,5,6])
sage: 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])
sage: 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
sage: Q = QuadraticForm(QQ, 7, range(28))
sage: 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 ]
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 ]
sage: 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 ]
Returns 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 : [[1, 2, 3, 1, 4], [2, 1, 1, 1, 1], [3, 1, 1, 1, 1]],
Genus symbol at 3 : [[0, 3, 1], [1, 1, -1]]]
Use the GHY formula to compute the mass of a (maximal?) quadratic lattice. This works for any number field.
Reference: See [GHY, Prop 7.4 and 7.5, p121] and [GY, Thrm 10.20, p25].
EXAMPLE:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.GHY_mass__maximal()
Gives 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
Returns a (symmetric) Gram matrix A for the quadratic form Q, meaning that
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
Returns a (symmetric) Gram matrix A for the quadratic form Q, meaning that
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
Returns the Hessian matrix A for which Q(X) = \((1/2) * X^t * A * X\).
EXAMPLES:
sage: Q = QuadraticForm(QQ, 2, range(1,4))
sage: 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
Returns 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”.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.Kitaoka_mass_at_2() ## WARNING: WE NEED TO CHECK THIS CAREFULLY!
1/2
Returns the local representation density of a form (for representing itself) defined over \(ZZ\), at some prime \(p>2\).
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
Returns 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.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.Watson_mass_at_2() ## WARNING: WE NEED TO CHECK THIS CAREFULLY!
384
Performs the substitution \(x_j --> x_j + c*x_i\), which has the effect (on associated matrices) of symmetrically adding \(c * 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 local_normal_form() method.
\(c\) – an element of Q.base_ring()
\(i\), \(j\) – integers >= 0
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: Oops! This coefficient can't 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 ]
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 ]
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 ]
Returns 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 ]
Returns a list with all of the anisotropic primes of the quadratic form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.anisotropic_primes()
[2]
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
sage: Q.anisotropic_primes()
[2]
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1])
sage: Q.anisotropic_primes()
[]
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()
Traceback (most recent call last):
...
ValueError: not an adjoint
Return a list of the automorphisms of the quadratic form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.number_of_automorphisms() # optional -- souvigner
48
sage: 2^3 * factorial(3)
48
sage: len(Q.automorphisms())
48
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q.number_of_automorphisms() # optional -- souvigner
16
sage: aut = Q.automorphisms()
sage: len(aut)
16
sage: print([Q(M) == Q for M in aut])
[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
sage: Q = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3])
sage: Q.automorphisms()
[
[1 0 0] [-1 0 0]
[0 1 0] [ 0 -1 0]
[0 0 1], [ 0 0 -1]
]
sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
sage: Q.automorphisms()
Traceback (most recent call last):
...
ValueError: not a definite form in QuadraticForm.automorphisms()
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.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ,[1,1]); Q
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 1 0 ]
[ * 1 ]
sage: Q1 = Q.base_change_to(IntegerModRing(5)); Q1
Quadratic form in 2 variables over Ring of integers modulo 5 with coefficients:
[ 1 0 ]
[ * 1 ]
sage: Q1([35,11])
1
Gives the ring over which the quadratic form is defined.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3])
sage: Q.base_ring()
Integer Ring
Finds a number represented by self and coprime to M.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [2, 1, 3])
sage: Q.basiclemma(6)
71
Finds 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
Return a basis for \(ZZ^n\) made of vectors with minimal lengths Q(\(v\)).
The safe_flag allows us to select whether we want a copy of the output, or the original output. By default safe_flag = True, so we return a copy of the cached information. If this is set to False, then the routine is much faster but the return values are vulnerable to being corrupted by the user.
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])
Returns 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
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
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
This does not work if the characteristic is 2:
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
Give the Cholesky decomposition of this quadratic form \(Q\) as a real matrix of precision bit_prec.
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]
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]
This is 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: 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()
2
sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor()
30
For hyperbolic spaces, the clifford conductor is 1:
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
This is the Clifford invariant, i.e. 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: 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
Gives 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]
Finds the \((n-1)\)-dim’l quadratic form orthogonal to the vector \(v\).
Note: This is usually not a direct summand!
Technical Notes: 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.
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:
[ 3 0 0 ]
[ * 5 0 ]
[ * * 7 ]
sage: Q1.complementary_subform_to_vector([1,1,0,0])
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 12 0 0 ]
[ * 5 0 ]
[ * * 7 ]
sage: Q1.complementary_subform_to_vector([1,1,1,1])
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 624 -480 -672 ]
[ * 880 -1120 ]
[ * * 1008 ]
Computes 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-dim’l form is considered both positive definite and negative definite.
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
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
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
Compute the (positive) definiteness of a quadratic form by looking at the signs of all of its upper-left subdeterminants. See also self.compute_definiteness() for more documentation.
sage: Q = DiagonalQuadraticForm(ZZ, [])
sage: Q.compute_definiteness_string_by_determinants()
'zero'
sage: Q = DiagonalQuadraticForm(ZZ, [1,0,-1])
sage: Q.compute_definiteness_string_by_determinants()
'degenerate'
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1])
sage: Q.compute_definiteness_string_by_determinants()
'indefinite'
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-1])
sage: Q.compute_definiteness_string_by_determinants()
'neg_def'
Returns 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 ]
Computes twice the power of p which evaluates the ‘cross product’ term in Conway’s mass formula.
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
Computes the diagonal factor of Conway’s \(p\)-mass.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,6))
sage: Q.conway_diagonal_factor(3)
81/256
Compute the mass by using the Conway-Sloane mass formula.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.conway_mass()
1/48
sage: Q = DiagonalQuadraticForm(ZZ, [7,1,1])
sage: Q.conway_mass()
3/16
sage: Q = QuadraticForm(ZZ, 3, [7, 2, 2, 2, 0, 2]) + DiagonalQuadraticForm(ZZ, [1])
sage: Q.conway_mass()
3/32
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 <= 2 and the 1x1 blocks are all in the upper leftmost position.
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
Computes Conway’s \(p\)-mass.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1, 6))
sage: Q.conway_p_mass(2)
16/3
sage: Q.conway_p_mass(3)
729/256
Returns an integer called the ‘species’ which determines the type of the orthogonal group over the finite field \(F_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 dim’l form is always 0+, so we interpret the return value of zero as positive here! =)
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,10))
sage: 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]
Returns an integer called the ‘species’ which determines the type of the orthogonal group over the finite field \(F_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 dim’l form is always 0+, so we interpret the return value of zero as positive here! =)
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,10))
sage: Q.conway_species_list_at_odd_prime(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]
Returns the infinite product of the standard mass factors.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [2, -2, 0, 3, -5, 4])
sage: Q.conway_standard_mass()
1/6
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.conway_standard_mass()
1/6
Computes the standard (generic) Conway-Sloane \(p\)-mass.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.conway_standard_p_mass(2)
2/3
This is a special factor only present in the mass formula when \(p=2\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8))
sage: Q.conway_type_factor()
4
Counts 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 > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list of integers in range(self.dim()), or None
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3])
sage: Q.count_congruence_solutions(3, 1, 0, None, None)
15
Counts 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 > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list 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
Counts 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 > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list 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
Counts 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 > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list 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
Counts 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 > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list 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
Counts 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 > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list 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
Gives 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 and nzvec (and therefore is counted) iff both of the following conditions hold:
- \(x[i] == 0 (mod p)\) for all \(i\) in zvec
- \(x[i] != 0 (mod p) for all i\) in nzvec
\(p\) – prime number > 0
\(k\) – an integer > 0
\(m\) – an integer (depending only on mod \(p^k\))
zvec, nzvec – a list of integers in range(self.dim()), or None
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]
Returns the number of solutions of \(Q(x) = m (mod p)\) of a non-degenerate quadratic form over the finite field \(Z/pZ\), 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.
\(p\) – a prime number > 2
\(m\) – an integer
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]
This is the omega of the adjoint form, which is the same as the omega of the reciprocal form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,37])
sage: Q.delta()
148
Gives the determinant of the Gram matrix of 2*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
Gives the number of variables of the quadratic form.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3])
sage: Q.dim()
2
Returns the discriminant of the quadratic form, defined as
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
Returns 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]
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.
\(c\) – an element of Q.base_ring()
\(i\) – an integer >= 0
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 ]
Perform the substitution \(x_i --> x_i + c*x_j\) (replacing the original form if the in_place flag is True).
\(c\) – an element of Q.base_ring()
\(i\), \(j\) – integers >= 0
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(1,11))
sage: 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 ]
sage: R = QuadraticForm(ZZ, 4, range(1,11))
sage: 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])
sage: 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 ]
Extract the variables (in order) whose indices are listed in var_indices, to give a new quadratic form.
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 ]
Finds 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.
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)
Finds the \(p\)-neighbor of this quadratic form associated to a given vector \(v\) satisfying:
Reference: Gonzalo Tornaria’s Thesis, Thrm 3.5, p34.
EXAMPLES:
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:
[ 3 10 0 -4 ]
[ * 9 0 -6 ]
[ * * 1 0 ]
[ * * * 2 ]
Finds 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 intial call, no \(v\) needs to be passed.
Returns vectors whose last non-zero 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.
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
Finds 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.
Warning
If there are local obstructions for this to happen, then this algorithm will never terminate... =( We should check for this too!
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [10,1,4])
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(1, 1)
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(1, 0)
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(2, 0)
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(2, 2)
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(3, 3)
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(3, 3)
sage: Q.find_primitive_p_divisible_vector__random(5) # random
(2, 0)
Returns 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
Returns the genus of a two times a quadratic form over ZZ. These are defined by a collection of local genus symbols (a la Chapter 15 of Conway-Sloane), 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]
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]
Determines if the given quadratic form has a Jordan decomposition equivalent to that of self.
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: 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
Returns 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
sage: Q = QuadraticForm(ZZ, 2, [4,5,6])
sage: Q.has_integral_Gram_matrix()
False
This is the product of all primes where the Hasse invariant equals -1
EXAMPLES:
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()
1
sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor()
10
Computes the Hasse invariant at a prime \(p\), as given on p55 of Cassels’s book. If Q is diagonal with coefficients \(a_i\), then the (Cassels) Hasse invariant is given by
where \((a,b)_p\) is the Hilbert symbol at \(p\). The underlying quadratic form must be non-degenerate over \(Q_p\) for this to make sense.
WARNING: This is different from the O’Meara Hasse invariant, which allows \(i <= j\) in the product. That is given by the method hasse_invariant__OMeara(p).
NOTE: We should really rename this hasse_invariant__Cassels(), and set hasse_invariant() as a front-end to it.
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)]
[1, 1, 1, 1, 1, 1, 1, 1]
sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)]
[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)]
[1, 1, 1, 1, 1, 1, 1, 1]
sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)]
[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)]
[-1, 1, 1, 1, 1, 1, 1, 1]
sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)]
[1, 1, 1, 1, 1, 1, 1, 1]
Computes the O’Meara Hasse invariant at a prime \(p\), as given on p167 of O’Meara’s book. If Q is diagonal with coefficients \(a_i\), then the (Cassels) Hasse invariant is given by
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).
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)]
[1, 1, 1, 1, 1, 1, 1, 1]
sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)]
[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)]
[1, 1, 1, 1, 1, 1, 1, 1]
sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)]
[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)]
[-1, 1, 1, 1, 1, 1, 1, 1]
sage: [Q.hasse_invariant__OMeara(p) for p in prime_range(20)]
[1, 1, 1, 1, 1, 1, 1, 1]
Determines 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()
False
sage: Q.adjoint().is_adjoint()
True
Checks if the quadratic form is anisotropic over the p-adic numbers \(Q_p\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1])
sage: Q.is_anisotropic(2)
True
sage: Q.is_anisotropic(3)
True
sage: Q.is_anisotropic(5)
False
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1])
sage: Q.is_anisotropic(2)
False
sage: Q.is_anisotropic(3)
False
sage: Q.is_anisotropic(5)
False
sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p)]).is_anisotropic(p) for p in prime_range(3, 30)]
[True, True, True, True, True, True, True, True, True]
sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), 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]
Determines if the given quadratic form is (positive or negative) definite.
Note: A degenerate form is considered neither definite nor indefinite. Note: The zero-dim’l form is considered indefinite.
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
Returns 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
Uses the Souvigner code to compute the number of automorphisms.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
sage: Q1 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2])
sage: M = Q.is_globally_equivalent__souvigner(Q1, True) ; M # optional -- souvigner
[ 0 0 -1]
[ 1 0 0]
[-1 1 1]
sage: Q1(M) == Q # optional -- souvigner
True
Determines if the current quadratic form is equivalent to the given form over ZZ. If return_matrix is True, then we also return the transformation matrix M so that self(M) == other.
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.(Q1) # optional -- souvigner
True
sage: MM = Q.is_globally_equivalent_to(Q1, return_matrix=True) # optional -- souvigner
sage: Q(MM) == Q1 # optional -- souvigner
True
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) # optional -- souvigner
False
sage: Q1.is_globally_equivalent_to(Q3) # optional -- souvigner
True
sage: M = Q1.is_globally_equivalent_to(Q3, True) ; M # optional -- souvigner
[-1 -1 0]
[ 1 1 1]
[-1 0 0]
sage: Q1(M) == Q3 # optional -- souvigner
True
sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
sage: Q.is_globally_equivalent_to(Q)
Traceback (most recent call last):
...
ValueError: not a definite form in QuadraticForm.is_globally_equivalent_to()
Checks if the quadratic form is a sum of hyperbolic planes over the p-adic numbers Q_p.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1])
sage: Q.is_hyperbolic("infinity")
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
Determines if the given quadratic form is indefinite.
Note: A degenerate form is considered neither definite nor indefinite. Note: The zero-dim’l form is not considered indefinite.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-3,-5])
sage: Q.is_indefinite()
False
sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5])
sage: Q.is_indefinite()
True
Checks if Q is isotropic over the p-adic numbers \(Q_p\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1])
sage: Q.is_isotropic(2)
False
sage: Q.is_isotropic(3)
False
sage: Q.is_isotropic(5)
True
sage: Q = DiagonalQuadraticForm(ZZ, [1,-1])
sage: Q.is_isotropic(2)
True
sage: Q.is_isotropic(3)
True
sage: Q.is_isotropic(5)
True
sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p)]).is_isotropic(p) for p in prime_range(3, 30)]
[False, False, False, False, False, False, False, False, False]
sage: [DiagonalQuadraticForm(ZZ, [1, -least_quadratic_nonresidue(p), 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]
Determines 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.
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) # optional -- souvigner
False
sage: Q1.is_locally_equivalent_to(Q2)
True
Determines if the rational number m is locally represented by the quadratic form.
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
Determines if the rational number m is locally represented by the quadratic form at the (possibly infinite) prime \(p\).
INPUT:
\(m\) – an integer
\(p\) – a prime number > 0 or ‘infinity’
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
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
Determines if the quadratic form represents \(Z_p\) for all finite/non-archimedean primes, and represents all real numbers.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: 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
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,-1])
sage: Q.is_locally_universal_at_all_places() # long time (8.5 s)
True
Determines if the quadratic form represents \(Z_p\) for all finite/non-archimedean primes.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: 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
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.is_locally_universal_at_all_primes()
False
Determines if the (integer-valued/rational) quadratic form represents all of \(Z_p\).
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
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
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,-1])
sage: Q.is_locally_universal_at_prime(infinity)
True
Determines if the given quadratic form is negative-definite.
Note: A degenerate form is considered neither definite nor indefinite. Note: The zero-dim’l form is considered both positive definite and negative definite.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [-1,-3,-5])
sage: Q.is_negative_definite()
True
sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5])
sage: Q.is_negative_definite()
False
Returns 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
Determines if the given quadratic form is positive-definite.
Note: A degenerate form is considered neither definite nor indefinite. Note: The zero-dim’l form is considered both positive definite and negative definite.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5])
sage: Q.is_positive_definite()
True
sage: Q = DiagonalQuadraticForm(ZZ, [1,-3,5])
sage: Q.is_positive_definite()
False
Determines if the given integer-valued form is primitive (i.e. 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
Determines 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
Determines 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
Determines 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
Returns 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 2x2 blocks are listed after the 1x1 blocks (which follows from the convention of the local_normal_form() method).
..note
The decomposition of each `L_i` into smaller block is not unique!
The safe_flag argument allows us to select whether we want a copy of the output, or the original output. By default safe_flag = True, so we return a copy of the cached information. If this is set to False, then the routine is much faster but the return values are vulnerable to being corrupted by the user.
INPUT:
OUTPUT:
A list of pairs \((s_i, L_i)\) where:
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 ])]
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 ])]
Returns 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.
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: Oops! The given quadratic form has a Jordan component with a negative scale exponent!
This routine requires an integer-matrix quadratic form for the output indexing to work properly!
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 ]]
Determines the level of the quadratic form over a PID, which is a generator for the smallest ideal \(N\) of \(R\) such that N * (the matrix of 2*Q)^(-1) is in R with diagonal in 2*R.
Over \(\ZZ\) this returns a non-negative 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
Returns the level of the quadratic form, defined as
level(B) for even dimension level(B)/4 for odd dimension
where 2Q(\(x\)) \(= x^t * B * 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
Determines the level of the quadratic form (over R), which is the smallest ideal N of R such that N * (the matrix of 2*Q)^(-1) is in R with diagonal in 2*R. (Caveat: This always returns the principal ideal when working over a field!)
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
Returns 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: 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()
[]
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']
Returns 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()
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 0 1 0 ]
[ * 4 3 3 ]
[ * * 6 3 ]
[ * * * 6 ]
Finds 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:
Q – quadratic form assumed to be block diagonal and p-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
Finds the Bad-type I local density of Q representing \(m\) at \(p\). (Assuming that p > 2 and Q is given in local diagonal form.)
Q – quadratic form assumed to be block diagonal and \(p\)-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
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
Finds the Bad-type local density of Q representing \(m\) at \(p\), allowing certain congruence conditions mod \(p\).
Q – quadratic form assumed to be block diagonal and p-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
Gives the local 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!
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
Finds the local density of Q representing \(m\) at \(p\), allowing certain congruence conditions mod \(p\).
Q – quadratic form assumed to be block diagonal and p-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
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
Returns the Conway-Sloane genus symbol of 2 times a quadratic form defined over ZZ at a prime number p. This is defined (in the Genus_Symbol_p_adic_ring() class in the quadratic_forms/genera subfolder) to be a list of tuples (one for each Jordan component p^m*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 Z/8Z
= 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) for a discussion of this convention.
INPUT:
-\(p\) – a prime number > 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3,4])
sage: Q.local_genus_symbol(2)
Genus symbol at 2 : [[1, 2, 3, 1, 4], [2, 1, 1, 1, 1], [3, 1, 1, 1, 1]]
sage: Q.local_genus_symbol(3)
Genus symbol at 3 : [[0, 3, 1], [1, 1, -1]]
sage: Q.local_genus_symbol(5)
Genus symbol at 5 : [[0, 4, 1]]
Finds the Good-type local density of Q representing \(m\) at \(p\). (Front end routine for parity specific routines for p.)
TO DO: Add Documentation about the additional congruence conditions Zvec and NZvec.
Q – quadratic form assumed to be block diagonal and p-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
Finds 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 and NZvec can be either a list of indices or None. Zvec = [] is equivalent to Zvec = None which both impose no additional conditions, but NZvec = [] returns no solutions always while NZvec = None imposes no additional condition.
WARNING: Here the indices passed in Zvec and NZvec 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 1x1, and so there the indices and Jordan blocks coincide.
TO DO: Add type checking for Zvec, NZvec, and that Q is in local normal form.
Q – quadratic form assumed to be block diagonal and 2-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3])
sage: Q.local_good_density_congruence_even(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
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)
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_good_density_congruence_even(1, None, None)
3/4
sage: Q.local_good_density_congruence_even(2, None, None)
1
sage: Q.local_good_density_congruence_even(5, None, None)
3/4
Finds 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 and NZvec can be either a list of indices or None. Zvec = [] is equivalent to Zvec = None which both impose no additional conditions, but NZvec = [] returns no solutions always while NZvec = None imposes no additional condition.
TO DO: Add type checking for Zvec, NZvec, and that Q is in local normal form.
Q – quadratic form assumed to be diagonal and p-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3])
sage: Q.local_good_density_congruence_odd(3, 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
Returns the a locally integrally equivalent quadratic form over the p-adic integers Z_p which gives the Jordan decomposition. The Jordan components are written as sums of blocks of size <= 2 and are arranged by increasing scale, and then by increasing norm. (This is equivalent to saying that we put the 1x1 blocks before the 2x2 blocks in each Jordan component.)
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 ]
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 ]
Gives 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!
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)
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
Finds 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.
Q – quadratic form assumed to be block diagonal and p-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
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
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 \(Z_p\), and are labeled by the \(Q_p\) square-classes \(t*(Q_p)^2\) with \(t\) given as follows:
\(p > 2\) ==> [ * 1 u p u p * * * * ]
\(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 \(Q_p\) square-class is not represented, while a positive number \(x\) indicates that \(t*p^{(2*x)} (Z_p)^2\) is locally represented but \(t*p^{(2*(x-1))}\) \((Z_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 * u * r^2\) with \(u = 1 (mod 8)\)
\(2^5 * u * r^2\) with \(u = 3 (mod 8)\)
\(2 * u * 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.
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]
Finds the Zero-type local density of Q representing \(m\) at \(p\), allowing certain congruence conditions mod p.
Q – quadratic form assumed to be block diagonal and \(p\)-integral
\(p\) – a prime number
\(m\) – an integer
Zvec, NZvec – non-repeating lists of integers in range(self.dim()) or None
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
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
Gives the mass of transformations (det 1 and -1).
WARNING: THIS IS BROKEN RIGHT NOW... =(
Optional Arguments:
REFERENCES:
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
sage: Q.mass__by_Siegel_densities()
1/384
sage: Q.mass__by_Siegel_densities() - (2^Q.dim() * factorial(Q.dim()))^(-1)
0
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.mass__by_Siegel_densities()
1/48
sage: Q.mass__by_Siegel_densities() - (2^Q.dim() * factorial(Q.dim()))^(-1)
0
Computes 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!!!
TO DO: Remove this routine, or try to compile it!
EXAMPLE:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.mass_at_two_by_counting_mod_power(1)
4
Returns the Hessian matrix A for which Q(X) = \((1/2) * X^t * A * X\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, range(6))
sage: Q.matrix()
[ 0 1 2]
[ 1 6 4]
[ 2 4 10]
Find a Minkowski-reduced form equivalent to the given one. This means that
for all \(s_i\) where GCD`(s_k, ... s_n) = 1`.
Note: When Q has dim <= 4 we can take all \(s_i\) in {1, 0, -1}.
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]
)
Find a Minkowski-reduced form equivalent to the given one. This means that
Q(\(v_k\)) <= Q(\(s_1 * v_1 + ... + s_n * v_n\))
for all \(s_i\) where GCD(\(s_k, ... s_n\)) = 1.
Note: When Q has dim <= 4 we can take all \(s_i\) in {1, 0, -1}.
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_for_4vars__SP()
(
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 29 -17 25 4 ]
[ * 30 -11 5 ]
[ * * 64 0 ]
[ * * * 77 ] ,
[ 0 1 0 0]
[ 1 0 0 -1]
[ 0 0 1 0]
[ 0 0 0 1]
)
Replace the variables \(x_i\) by \(c*x_i\) 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.
\(c\) – an element of Q.base_ring()
\(i\) – an integer >= 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,9,5,7])
sage: Q.multiply_variable(5,0)
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 25 0 0 0 ]
[ * 9 0 0 ]
[ * * 5 0 ]
[ * * * 7 ]
Return a list of the number of automorphisms (of det 1 and -1) of the quadratic form.
If recompute is True, then we will recompute the cached result.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [1, 0, 0, 1, 0, 1], unsafe_initialization=True, number_of_automorphisms=-1)
sage: Q.list_external_initializations()
['number_of_automorphisms']
sage: Q.number_of_automorphisms()
-1
sage: Q.number_of_automorphisms(recompute=True) # optional -- souvigner
48
sage: Q.list_external_initializations() # optional -- souvigner
[]
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
sage: Q.number_of_automorphisms() # optional -- souvigner
384
sage: 2^4 * factorial(4)
384
sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
sage: Q.number_of_automorphisms()
Traceback (most recent call last):
...
ValueError: not a definite form in QuadraticForm.number_of_automorphisms()
Uses the Souvigner code to compute the number of automorphisms.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1,1])
sage: Q.number_of_automorphisms__souvigner() # optional -- souvigner
3840
sage: 2^5 * factorial(5)
3840
This is the content of the adjoint of the primitive associated quadratic form.
Ref: See Dickson’s “Studies in Number Theory”.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,37])
sage: Q.omega()
4
Returns the parity (“even” or “odd”) of an integer-valued quadratic form over \(ZZ\), defined up to similitude/rescaling of the form so that its Jordan component of smallest scale is unimodular. After this rescaling, we say a form is even if it only represents even numbers, and odd if it represents some odd number.
If the ‘allow_rescaling_flag’ is set to False, then we require that the quadratic form have a Gram matrix with coefficients in \(ZZ\), and look at the unimodular Jordan block to determine its parity. This returns an error if the form is not integer-matrix, meaning that it has Jordan components at \(p=2\) which do not have an integer scale.
We determine the parity by looking for a 1x1 block in the 0-th Jordan component, after a possible rescaling.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 3, 2]); Q
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 4 -2 0 ]
[ * 2 3 ]
[ * * 2 ]
sage: Q.parity()
'even'
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 3, 1]); Q
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 4 -2 0 ]
[ * 2 3 ]
[ * * 1 ]
sage: Q.parity()
'even'
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 2, 2]); Q
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 4 -2 0 ]
[ * 2 2 ]
[ * * 2 ]
sage: Q.parity()
'even'
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 2, 1]); Q
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 4 -2 0 ]
[ * 2 2 ]
[ * * 1 ]
sage: Q.parity()
'odd'
Returns the polynomial in ‘n’ variables of the quadratic form in the ring ‘R[names].’
INPUT:
-‘self’ - a quadratic form over a commatitive ring. -‘names’ - the name of the variables. Digits will be appended to the name for each different canonical variable e.g x1, x2, x3 etc.
OUTPUT:
The polynomial form of the quadratic form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(QQ,[1, 3, 5, 7])
sage: P = Q.polynomial(); P
2*x0^2 + 6*x1^2 + 10*x2^2 + 14*x3^2
sage: F.<a> = NumberField(x^2 - 5)
sage: Z = F.ring_of_integers()
sage: Q = QuadraticForm(Z,3,[2*a, 3*a, 0 , 1 - a, 0, 2*a + 4])
sage: P = Q.polynomial(names='y'); P
4*a*y0^2 + 6*a*y0*y1 + (-2*a + 2)*y1^2 + (4*a + 8)*y2^2
sage: Q = QuadraticForm(F,4,[a, 3*a, 0, 1 - a, a - 3, 0, 2*a + 4, 4 + a, 0, 1])
sage: Q.polynomial(names='z')
(2*a)*z0^2 + (6*a)*z0*z1 + (2*a - 6)*z1^2 + (2*a + 8)*z2^2 + (-2*a + 2)*z0*z3 + (4*a + 8)*z1*z3 + 2*z3^2
sage: B.<i,j,k> = QuaternionAlgebra(F,-1,-1)
sage: Q = QuadraticForm(B, 3, [2*a, 3*a, i, 1 - a, 0, 2*a + 4])
sage: Q.polynomial()
Traceback (most recent call last):
...
ValueError: Can only create polynomial rings over commutative rings.
Returns a primitive version of an integer-valued quadratic form, defined over \(ZZ\).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [2,3,4])
sage: Q.primitive()
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 2 3 ]
[ * 4 ]
sage: Q = QuadraticForm(ZZ, 2, [2,4,8])
sage: Q.primitive()
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 1 2 ]
[ * 4 ]
Returns a diagonal form equivalent to Q over the fraction field of its defining ring. If the return_matrix is True, then we return the transformation matrix performing the diagonalization as the second argument.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [0,1,-1])
sage: Q
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 0 1 ]
[ * -1 ]
sage: Q.rational_diagonal_form()
Quadratic form in 2 variables over Rational Field with coefficients:
[ -2 0 ]
[ * 1/8 ]
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q.rational_diagonal_form(return_matrix=True)
(
Quadratic form in 4 variables over Rational Field with coefficients:
[ 1 0 0 0 ]
[ * 3 0 0 ]
[ * * 5 0 ]
[ * * * 7 ] ,
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
)
sage: Q1 = QuadraticForm(ZZ, 4, [1, 1, 0, 0, 1, 0, 0, 1, 0, 18])
sage: Q1
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 1 0 0 ]
[ * 1 0 0 ]
[ * * 1 0 ]
[ * * * 18 ]
sage: Q1.rational_diagonal_form(return_matrix=True)
(
Quadratic form in 4 variables over Rational Field with coefficients:
[ 1 0 0 0 ]
[ * 3/4 0 0 ]
[ * * 1 0 ]
[ * * * 18 ] ,
[ 1 -1/2 0 0]
[ 0 1 0 0]
[ 0 0 1 0]
[ 0 0 0 1]
)
This gives the reciprocal quadratic form associated to the given form. This is defined as the multiple of the primitive adjoint with the same content as the given form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,37])
sage: Q.reciprocal()
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 37 0 0 ]
[ * 37 0 ]
[ * * 1 ]
sage: Q.reciprocal().reciprocal()
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 1 0 0 ]
[ * 1 0 ]
[ * * 37 ]
sage: Q.reciprocal().reciprocal() == Q
True
Find a form which is reduced in the sense that no further binary form reductions can be done to reduce the original form.
EXAMPLES:
sage: QuadraticForm(ZZ,2,[5,5,2]).reduced_binary_form()
(
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 2 -1 ]
[ * 2 ] ,
[ 0 -1]
[ 1 1]
)
Reduce the form \(ax^2 + bxy+cy^2\) to satisfy the reduced condition \(|b| \le a \le c\), with \(b \ge 0\) if \(a = c\). This reduction occurs within the proper class, so all transformations are taken to have determinant 1.
EXAMPLES:
sage: QuadraticForm(ZZ,2,[5,5,2]).reduced_binary_form1()
(
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 2 -1 ]
[ * 2 ] ,
[ 0 -1]
[ 1 1]
)
Find the unique reduced ternary form according to the conditions of Dickson’s “Studies in the Theory of Numbers”, pp164-171.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1, 1, 1])
sage: Q.reduced_ternary_form__Dickson()
Traceback (most recent call last):
...
NotImplementedError: TO DO
Returns the vector of representation numbers < B.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ,[1,1,1,1,1,1,1,1])
sage: Q.representation_number_list(10)
[1, 16, 112, 448, 1136, 2016, 3136, 5504, 9328, 12112]
Find all vectors v where Q(v) < B.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1, 1])
sage: Q.representation_vector_list(10)
[[(0, 0)],
[(0, 1), (0, -1), (1, 0), (-1, 0)],
[(1, 1), (-1, -1), (-1, 1), (1, -1)],
[],
[(0, 2), (0, -2), (2, 0), (-2, 0)],
[(1, 2), (-1, -2), (-1, 2), (1, -2), (2, 1), (-2, -1), (-2, 1), (2, -1)],
[],
[],
[(2, 2), (-2, -2), (-2, 2), (2, -2)],
[(0, 3), (0, -3), (3, 0), (-3, 0)]]
sage: map(len, _)
[1, 4, 4, 0, 4, 8, 0, 0, 4, 4]
sage: Q.representation_number_list(10)
[1, 4, 4, 0, 4, 8, 0, 0, 4, 4]
Scale the values of the quadratic form by the number \(c\), if this is possible while still being defined over its base ring.
If the flag is set to true, then this will alter the value ring to be the field of fractions of the original ring (if necessary).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [3,9,18,27])
sage: Q.scale_by_factor(3)
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 9 0 0 0 ]
[ * 27 0 0 ]
[ * * 54 0 ]
[ * * * 81 ]
sage: Q.scale_by_factor(1/3)
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 0 0 0 ]
[ * 3 0 0 ]
[ * * 6 0 ]
[ * * * 9 ]
Set the number of automorphisms to be the value given. No error checking is performed, to this may lead to erroneous results.
The fact that this result was set externally is recorded in the internal list of external initializations, accessible by the method list_external_initializations().
Return a list of the number of automorphisms (of det 1 and -1) of the quadratic form.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1, 1, 1])
sage: Q.list_external_initializations()
[]
sage: Q.set_number_of_automorphisms(-3)
sage: Q.number_of_automorphisms()
-3
sage: Q.list_external_initializations()
['number_of_automorphisms']
Use Shimura’s exact mass formula to compute the mass of a maximal quadratic lattice. This works for any totally real number field, but has a small technical restriction when \(n\) is odd.
EXAMPLE:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
sage: Q.shimura_mass__maximal()
Return a list of lists of short primitive vectors \(v\), sorted by length, with Q(\(v\)) < len_bound. The list in output \([i]\) indexes all vectors of length \(i\). If the up_to_sign_flag is set to True, then only one of the vectors of the pair \([v, -v]\) is listed.
Note: This processes the PARI/GP output to always give elements of type \(ZZ\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q.short_vector_list_up_to_length(5, True)
[[(0, 0, 0, 0)],
[(1, 0, 0, 0)],
[],
[(0, 1, 0, 0)],
[(1, 1, 0, 0), (-1, 1, 0, 0), (2, 0, 0, 0)]]
sage: Q.short_primitive_vector_list_up_to_length(5, True)
[[], [(1, 0, 0, 0)], [], [(0, 1, 0, 0)], [(1, 1, 0, 0), (-1, 1, 0, 0)]]
Return a list of lists of short vectors \(v\), sorted by length, with Q(\(v\)) < len_bound. The list in output \([i]\) indexes all vectors of length \(i\). If the up_to_sign_flag is set to True, then only one of the vectors of the pair \([v, -v]\) is listed.
Note: This processes the PARI/GP output to always give elements of type \(ZZ\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q.short_vector_list_up_to_length(3)
[[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], []]
sage: Q.short_vector_list_up_to_length(4)
[[(0, 0, 0, 0)],
[(1, 0, 0, 0), (-1, 0, 0, 0)],
[],
[(0, 1, 0, 0), (0, -1, 0, 0)]]
sage: Q.short_vector_list_up_to_length(5)
[[(0, 0, 0, 0)],
[(1, 0, 0, 0), (-1, 0, 0, 0)],
[],
[(0, 1, 0, 0), (0, -1, 0, 0)],
[(1, 1, 0, 0),
(-1, -1, 0, 0),
(-1, 1, 0, 0),
(1, -1, 0, 0),
(2, 0, 0, 0),
(-2, 0, 0, 0)]]
sage: Q.short_vector_list_up_to_length(5, True)
[[(0, 0, 0, 0)],
[(1, 0, 0, 0)],
[],
[(0, 1, 0, 0)],
[(1, 1, 0, 0), (-1, 1, 0, 0), (2, 0, 0, 0)]]
sage: Q = QuadraticForm(matrix(6, [2, 1, 1, 1, -1, -1, 1, 2, 1, 1, -1, -1, 1, 1, 2, 0, -1, -1, 1, 1, 0, 2, 0, -1, -1, -1, -1, 0, 2, 1, -1, -1, -1, -1, 1, 2]))
sage: vs = Q.short_vector_list_up_to_length(40) #long time
The cases of len_bound < 2 led to exception or infinite runtime before.
sage: Q.short_vector_list_up_to_length(0)
[]
sage: Q.short_vector_list_up_to_length(1)
[[(0, 0, 0, 0, 0, 0)]]
In the case of quadratic forms that are not positive definite an error is raised.
sage: QuadraticForm(matrix(2, [2, 0, 0, -2])).short_vector_list_up_to_length(3)
Traceback (most recent call last):
...
ValueError: Quadratic form must be positive definite in order to enumerate short vectors
Sometimes, Pari does not compute short vectors correctly. It returns too long vectors.
sage: mat = matrix(2, [72, 12, 12, 120]) #long time
sage: len_bound = 22953421 #long time
sage: gp_mat = gp.qfminim(str(gp(mat)), 2 * len_bound - 2)[3] #long time
sage: rows = [ map(ZZ, str(gp_mat[i,])[1:-1].split(',')) for i in range(1, gp_mat.matsize()[1] + 1) ] #long time
sage: vec_list = map(vector, zip(*rows)) #long time
sage: eval_v_cython = cython_lambda( ", ".join( "int a{0}".format(i) for i in range(2) ), " + ".join( "{coeff} * a{i} * a{j}".format(coeff = mat[i,j], i = i, j = j) for i in range(2) for j in range(2) ) ) #long time
sage: any( eval_v_cython(*v) == 2 * 22955664 for v in vec_list ) # 22955664 > 22953421 = len_bound #long time
True
Computes the infinite product of local densities of the quadratic form for the number \(u\).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
sage: Q.theta_series(11)
1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10 + O(q^11)
sage: Q.siegel_product(1)
8
sage: Q.siegel_product(2) ## This one is wrong -- expect 24, and the higher powers of 2 don't work... =(
24
sage: Q.siegel_product(3)
32
sage: Q.siegel_product(5)
48
sage: Q.siegel_product(6)
96
sage: Q.siegel_product(7)
64
sage: Q.siegel_product(9)
104
sage: Q.local_density(2,1)
1
sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3
1
sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3 # long time (41s on sage.math, 2011)
1
sage: Q.local_density(2,2)
3/2
sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3
3/2
sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3 # long time (41s on sage.math, 2011)
3/2
TESTS:
sage: [1] + [Q.siegel_product(ZZ(a)) for a in range(1,11)] == Q.theta_series(11).list()
True
Returns the signature of the quadratic form, defined as:
number of positive eigenvalues - number of negative eigenvalues
of the matrix of the quadratic form.
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,-3,-4])
sage: Q.signature()
0
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.signature()
2
Returns the triple \((p, n, z)\) of integers where
for the symmetric matrix associated to Q.
INPUT:
(none)
OUTPUT:
a triple of integers >= 0
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,0,0,-4])
sage: Q.signature_vector()
(1, 1, 2)
sage: Q = DiagonalQuadraticForm(ZZ, [1,2,-3,-4])
sage: Q.signature_vector()
(2, 2, 0)
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.signature_vector()
(3, 1, 0)
Tries to find subform of the given (positive definite quaternary) quadratic form Q of the form
where \(d > 0\) is as small as possible.
This is done by exhaustive search on small vectors, and then comparing the local conditions of its sum with it’s complementary lattice and the original quadratic form Q.
EXAMPLES:
sage: Q1 = DiagonalQuadraticForm(ZZ, [7,5,3])
sage: Q1.split_local_cover()
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 3 0 0 ]
[ * 7 0 ]
[ * * 5 ]
Returns the sum (on coefficients) of two quadratic forms of the same size.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,4,10])
sage: Q
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 1 4 ]
[ * 10 ]
sage: Q+Q
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 4 0 0 ]
[ * 10 0 0 ]
[ * * 1 4 ]
[ * * * 10 ]
sage: Q2 = QuadraticForm(ZZ, 2, [1,4,-10])
sage: Q.sum_by_coefficients_with(Q2)
Quadratic form in 2 variables over Integer Ring with coefficients:
[ 2 8 ]
[ * 0 ]
Switch the variables \(x_r\) and \(x_s\) in the quadratic form (replacing the original form if the in_place flag is True).
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 4, range(1,11))
sage: Q
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 2 3 4 ]
[ * 5 6 7 ]
[ * * 8 9 ]
[ * * * 10 ]
sage: Q.swap_variables(0,2)
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 8 6 3 9 ]
[ * 5 2 7 ]
[ * * 1 4 ]
[ * * * 10 ]
sage: Q.swap_variables(0,2).swap_variables(0,2)
Quadratic form in 4 variables over Integer Ring with coefficients:
[ 1 2 3 4 ]
[ * 5 6 7 ]
[ * * 8 9 ]
[ * * * 10 ]
Uses the real Cholesky decomposition to compute (the \(q\)-expansion of) the theta function of the quadratic form as a power series in \(q\) with terms correct up to the power \(q^{\text{q\_prec}}\). (So its error is \(O(q^ {\text{q\_prec} + 1})\).)
EXAMPLES:
## Check the sum of 4 squares form against Jacobi's formula
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
sage: Theta = Q.theta_by_cholesky(10)
sage: Theta
1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10
sage: Expected = [1] + [8*sum([d for d in divisors(n) if d%4 != 0]) for n in range(1,11)]
sage: Expected
[1, 8, 24, 32, 24, 48, 96, 64, 24, 104, 144]
sage: Theta.list() == Expected
True
## Check the form x^2 + 3y^2 + 5z^2 + 7w^2 represents everything except 2 and 22.
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Theta = Q.theta_by_cholesky(50)
sage: Theta_list = Theta.list()
sage: [m for m in range(len(Theta_list)) if Theta_list[m] == 0]
[2, 22]
Use PARI/GP to compute the theta function as a power series (or vector) up to the precision \(O(q^Max)\). This also caches the result for future computations.
If var_str = ‘’, then we return a vector \(v\) where \(v[i]\) counts the number of vectors of length \(i\).
The safe_flag allows us to select whether we want a copy of the output, or the original output. It is only meaningful when a vector is returned, otherwise a copy is automatically made in creating the power series. By default safe_flag = True, so we return a copy of the cached information. If this is set to False, then the routine is much faster but the return values are vulnerable to being corrupted by the user.
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
sage: Prec = 100
sage: compute = Q.theta_by_pari(Prec, '')
sage: exact = [1] + [8 * sum([d for d in divisors(i) if d % 4 != 0]) for i in range(1, Prec)]
sage: compute == exact
True
Compute the theta series as a power series in the variable given in var_str (which defaults to ‘\(q\)‘), up to the specified precision \(O(q^max)\).
This uses the PARI/GP function qfrep, wrapped by the theta_by_pari() method. This caches the result for future computations.
The safe_flag allows us to select whether we want a copy of the output, or the original output. It is only meaningful when a vector is returned, otherwise a copy is automatically made in creating the power series. By default safe_flag = True, so we return a copy of the cached information. If this is set to False, then the routine is much faster but the return values are vulnerable to being corrupted by the user.
TO DO: Allow the option Max=’mod_form’ to give enough coefficients to ensure we determine the theta series as a modular form. This is related to the Sturm bound, but we’ll need to be careful about this (particularly for half-integral weights!).
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q.theta_series()
1 + 2*q + 2*q^3 + 6*q^4 + 2*q^5 + 4*q^6 + 6*q^7 + 8*q^8 + 14*q^9 + O(q^10)
sage: Q.theta_series(25)
1 + 2*q + 2*q^3 + 6*q^4 + 2*q^5 + 4*q^6 + 6*q^7 + 8*q^8 + 14*q^9 + 4*q^10 + 12*q^11 + 18*q^12 + 12*q^13 + 12*q^14 + 8*q^15 + 34*q^16 + 12*q^17 + 8*q^18 + 32*q^19 + 10*q^20 + 28*q^21 + 16*q^23 + 44*q^24 + O(q^25)
Compute the theta series of degree 2 for the quadratic form Q.
INPUT:
OUTPUT:
dictionary, where:
EXAMPLES:
sage: Q2 = QuadraticForm(ZZ, 4, [1,1,1,1, 1,0,0, 1,0, 1])
sage: S = Q2.theta_series_degree_2(10)
sage: S[(0,0,2)]
24
sage: S[(1,0,1)]
144
sage: S[(1,1,1)]
192
AUTHORS:
REFERENCE:
Returns a list of short vectors together with their values.
This is a naive algorithm which uses the Cholesky decomposition, but does not use the LLL-reduction algorithm.
Reference: This is a slightly modified version of Cohn’s Algorithm 2.7.5 in “A Course in Computational Number Theory”, with the increment step moved around and slightly re-indexed to allow clean looping.
Note: We could speed this up for very skew matrices by using LLL first, and then changing coordinates back, but for our purposes the simpler method is efficient enough. =)
EXAMPLES:
sage: Q = DiagonalQuadraticForm(ZZ, [1,1])
sage: Q.vectors_by_length(5)
[[[0, 0]],
[[0, -1], [-1, 0]],
[[-1, -1], [1, -1]],
[],
[[0, -2], [-2, 0]],
[[-1, -2], [1, -2], [-2, -1], [2, -1]]]
sage: Q1 = DiagonalQuadraticForm(ZZ, [1,3,5,7])
sage: Q1.vectors_by_length(5)
[[[0, 0, 0, 0]],
[[-1, 0, 0, 0]],
[],
[[0, -1, 0, 0]],
[[-1, -1, 0, 0], [1, -1, 0, 0], [-2, 0, 0, 0]],
[[0, 0, -1, 0]]]
sage: Q = QuadraticForm(ZZ, 4, [1,1,1,1, 1,0,0, 1,0, 1])
sage: map(len, Q.vectors_by_length(2))
[1, 12, 12]
sage: Q = QuadraticForm(ZZ, 4, [1,-1,-1,-1, 1,0,0, 4,-3, 4])
sage: map(len, Q.vectors_by_length(3))
[1, 3, 0, 3]
Return the value of the genus characters Xi_p... which may be missing one character. We allow -1 as a prime.
Reference: Dickson’s “Studies in the Theory of Numbers”
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 1, 1, 14, 3, 14])
sage: Q2 = QuadraticForm(ZZ, 3, [2, -1, 0, 2, 0, 50])
sage: [Q1.omega(), Q2.omega()]
[5, 5]
sage: [Q1.hasse_invariant(5), Q2.hasse_invariant(5)] # equivalent over Q_5
[1, 1]
sage: [Q1.xi(5), Q2.xi(5)] # not equivalent over Z_5
[1, -1]
Returns Xi(\(p\)) for the reciprocal form.
EXAMPLES:
sage: Q1 = QuadraticForm(ZZ, 3, [1, 1, 1, 14, 3, 14])
sage: Q2 = QuadraticForm(ZZ, 3, [2, -1, 0, 2, 0, 50])
sage: [Q1.clifford_conductor(), Q2.clifford_conductor()] # equivalent over Q
[3, 3]
sage: Q1.is_locally_equivalent_to(Q2) # not in the same genus
False
sage: [Q1.delta(), Q2.delta()]
[480, 480]
sage: factor(480)
2^5 * 3 * 5
sage: map(Q1.xi_rec, [-1,2,3,5])
[-1, -1, -1, 1]
sage: map(Q2.xi_rec, [-1,2,3,5])
[-1, -1, -1, -1]
Wrapper for the QuadraticForm class constructor. This is meant for internal use within the QuadraticForm class code only. You should instead directly call QuadraticForm().
EXAMPLES:
sage: from sage.quadratic_forms.quadratic_form import QuadraticForm__constructor
sage: QuadraticForm__constructor(ZZ, 3) ## Makes a generic quadratic form over the integers
Quadratic form in 3 variables over Integer Ring with coefficients:
[ 0 0 0 ]
[ * 0 0 ]
[ * * 0 ]
Determines if the object Q is an element of the QuadraticForm class.
EXAMPLES:
sage: Q = QuadraticForm(ZZ, 2, [1,2,3])
sage: is_QuadraticForm(Q) ##random -- deprecated
True
sage: is_QuadraticForm(2) ##random -- deprecated
False