Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Resolved merge conflict in imports
Browse files Browse the repository at this point in the history
Merge branch 't/24864/bug_in_torsionquadraticform_normal_form__' into t/24577/is_genus_for_torsion_quadratic_modules

Conflicts:
	src/sage/modules/torsion_quadratic_module.py
  • Loading branch information
Simon Brandhorst committed Mar 1, 2018
2 parents 2251c52 + 893ba1c commit 266391f
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 13 deletions.
95 changes: 87 additions & 8 deletions src/sage/modules/torsion_quadratic_module.py
Expand Up @@ -20,7 +20,7 @@
from sage.modules.fg_pid.fgp_module import FGP_Module_class
from sage.modules.fg_pid.fgp_element import DEBUG, FGP_Element
from sage.arith.misc import gcd
from sage.rings.all import ZZ, QQ, IntegerModRing
from sage.rings.all import ZZ, Zp, QQ, IntegerModRing
from sage.groups.additive_abelian.qmodnz import QmodnZ
from sage.matrix.constructor import matrix
from sage.misc.cachefunc import cached_method
Expand Down Expand Up @@ -584,6 +584,40 @@ def normal_form(self, partial=False):
EXAMPLES::
sage: L1=IntegralLattice(matrix([[-2,0,0],[0,1,0],[0,0,4]]))
sage: L1.discriminant_group().normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4)
Gram matrix of the quadratic form with values in Q/Z:
[1/2 0]
[ 0 1/4]
sage: L2=IntegralLattice(matrix([[-2,0,0],[0,1,0],[0,0,-4]]))
sage: L2.discriminant_group().normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4)
Gram matrix of the quadratic form with values in Q/Z:
[1/2 0]
[ 0 1/4]
We check that :trac:`24864` is fixed::
sage: L1=IntegralLattice(matrix([[-4,0,0],[0,4,0],[0,0,-2]]))
sage: AL1=L1.discriminant_group()
sage: L2=IntegralLattice(matrix([[-4,0,0],[0,-4,0],[0,0,2]]))
sage: AL2=L2.discriminant_group()
sage: AL1.normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4, 4)
Gram matrix of the quadratic form with values in Q/2Z:
[1/2 0 0]
[ 0 1/4 0]
[ 0 0 5/4]
sage: AL2.normal_form()
Finite quadratic module over Integer Ring with invariants (2, 4, 4)
Gram matrix of the quadratic form with values in Q/2Z:
[1/2 0 0]
[ 0 1/4 0]
[ 0 0 5/4]
Some exotic cases::
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
sage: D4_gram = Matrix(ZZ,4,4,[2,0,0,-1,0,2,0,-1,0,0,2,-1,-1,-1,-1,2])
sage: D4 = FreeQuadraticModule(ZZ,4,D4_gram)
Expand All @@ -599,26 +633,71 @@ def normal_form(self, partial=False):
sage: T.normal_form()
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
Gram matrix of the quadratic form with values in Q/(1/3)Z:
[1/12 1/24 0 0 0 0 0 0]
[1/24 1/12 0 0 0 0 0 0]
[ 0 0 1/6 1/12 0 0 0 0]
[ 0 0 1/12 1/6 0 0 0 0]
[ 1/6 1/12 0 0 0 0 0 0]
[1/12 1/6 0 0 0 0 0 0]
[ 0 0 1/12 1/24 0 0 0 0]
[ 0 0 1/24 1/12 0 0 0 0]
[ 0 0 0 0 1/9 0 0 0]
[ 0 0 0 0 0 1/9 0 0]
[ 0 0 0 0 0 0 1/9 0]
[ 0 0 0 0 0 0 0 1/9]
TESTS:
A degenerate case::
sage: T = TorsionQuadraticModule((1/6)*D4dual, D4, modulus=1/36)
sage: T.normal_form()
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
Gram matrix of the quadratic form with values in Q/(1/18)Z:
[1/36 1/72 0 0 0 0 0 0]
[1/72 1/36 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
"""
gens = []
from sage.quadratic_forms.genera.normal_form import p_adic_normal_form
from sage.quadratic_forms.genera.normal_form import p_adic_normal_form, _normalize
for p in self.annihilator().gen().prime_divisors():
D_p = self.primary_part(p)
q_p = D_p.gram_matrix_quadratic()
q_p = q_p / D_p._modulus_qf

# continue with the non-degenerate part
r = q_p.rank()
if r != q_p.ncols():
U = q_p._clear_denom()[0].hermite_form(transformation=True)[1]
else:
U = q_p.parent().identity_matrix()
kernel = U[r:,:]
nondeg = U[:r,:]
q_p = nondeg * q_p * nondeg.T

# the normal form is implemented for p-adic lattices
# so we should work with the lattice q_p --> q_p^-1
q_p1 = q_p.inverse()
prec = self.annihilator().gen().valuation(p) + 5
D, U = p_adic_normal_form(q_p, p, precision=prec, partial=False)
D, U = p_adic_normal_form(q_p1, p, precision=prec + 5, partial=partial)
# if we compute the inverse in the p-adics everything explodes --> go to ZZ
U = U.change_ring(ZZ).inverse().transpose()

# the inverse is in normal form - so to get a normal form for the original one
# it is enough to massage each 1x1 resp. 2x2 block.
U = U.change_ring(Zp(p, type='fixed-mod', prec=prec)).change_ring(ZZ)
D = U * q_p * U.T * p**q_p.denominator().valuation(p)
D = D.change_ring(Zp(p, type='fixed-mod', prec=prec))
_, U1 = _normalize(D, normal_odd=False)
U = U1.change_ring(ZZ) * U

# reattach the degenerate part
nondeg = U * nondeg
U = nondeg.stack(kernel)

#apply U to the generators
n = U.ncols()
U = U.change_ring(ZZ)
gens_p = []
for i in range(n):
g = self.V().zero()
Expand Down
12 changes: 7 additions & 5 deletions src/sage/quadratic_forms/genera/normal_form.py
Expand Up @@ -755,16 +755,18 @@ def _min_nonsquare(p):
if not R(i).is_square():
return i

def _normalize(G):
def _normalize(G, normal_odd=True):
r"""
Return the transformation to sums of forms of types `U`, `V` and `W`.
Part of the algorithm :meth:`p_adic_normal_form`.
INPUT:
- a symmetric matrix over `\ZZ_p` in jordan form --
- ``G`` -- a symmetric matrix over `\ZZ_p` in jordan form --
the output of :meth:`p_adic_normal_form` or :meth:`_jordan_2_adic`
- ``normal_odd`` -- bool (default: True) if true and `p` is odd,
compute a normal form.
OUTPUT:
Expand Down Expand Up @@ -804,7 +806,7 @@ def _normalize(G):
if D[i,i].valuation() > val:
# a new block starts
val = D[i,i].valuation()
if len(non_squares) != 0:
if normal_odd and len(non_squares) != 0:
# move the non-square to
# the last entry of the previous block
j = non_squares.pop()
Expand All @@ -816,7 +818,7 @@ def _normalize(G):
else:
D[i, i] = v
B[i, :] *= (v * d.inverse_of_unit()).sqrt()
if len(non_squares) != 0:
if normal_odd and len(non_squares) != 0:
# we combine two non-squares to get
# the 2 x 2 identity matrix
j = non_squares.pop()
Expand All @@ -826,7 +828,7 @@ def _normalize(G):
D[j,j] = 1
else:
non_squares.append(i)
if len(non_squares) != 0:
if normal_odd and len(non_squares) != 0:
j=non_squares.pop()
B.swap_rows(j,n-1)
else:
Expand Down

0 comments on commit 266391f

Please sign in to comment.