Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Reduction Theory """ from copy import deepcopy from sage.matrix.constructor import matrix from sage.functions.all import floor from sage.misc.mrange import mrange from sage.modules.free_module_element import vector from sage.rings.integer_ring import ZZ
def reduced_binary_form1(self): r""" 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 ] , <BLANKLINE> [ 0 -1] [ 1 1] ) """ raise TypeError("This must be a binary form for now...")
## Arrange for a <= c #print "A"
## Arrange for |b| <= a #print "B"
def reduced_ternary_form__Dickson(self): """ 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
"""
def reduced_binary_form(self): """ 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 ] , <BLANKLINE> [ 0 -1] [ 1 1] ) """
#print Q
## Arrange for (weakly) increasing diagonal entries
#print "A"
## Arrange for |b| <= a r = R(floor(round(Q[i,j]/(2*Q[i,i]))))
M_new = matrix(R,n,n) for k in range(n): M_new[k,k] = 1 M_new[i,j] = -r
Q = Q(M_new) M = M * M_new interior_reduced_flag = False #print "B"
def minkowski_reduction(self): """ Find a Minkowski-reduced form equivalent to the given one. This means that
.. MATH::
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}.
References: Schulze-Pillot's paper on "An algorithm for computing genera of ternary and quaternary quadratic forms", p138. Donaldson's 1979 paper "Minkowski Reduction of Integral Matrices", p203.
EXAMPLES::
sage: Q = QuadraticForm(ZZ,4,[30,17,11,12,29,25,62,64,25,110]) sage: Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 12 ] [ * 29 25 62 ] [ * * 64 25 ] [ * * * 110 ] sage: Q.minkowski_reduction() ( Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 -5 ] [ * 29 25 4 ] [ * * 64 0 ] [ * * * 77 ] , <BLANKLINE> [ 1 0 0 0] [ 0 1 0 -1] [ 0 0 1 0] [ 0 0 0 1] ) """
## Begin the reduction
## Loop through possible shorted vectors until #print " j_range = ", range(n-1, -1, -1) #print "j = ", j
## Reduce if a shorter vector is found #print "y = ", y, " e_j = ", e_j, "\n"
## Create the transformation matrix
## Perform the reduction and restart the loop #print "Q_before = ", Q
## DIAGNOSTIC #print "Q(y) = ", Q(y) #print "Q(e_j) = ", Q(e_j) #print "M_new = ", M_new #print "Q_after = ", Q
## Return the results
def minkowski_reduction_for_4vars__SP(self): """ 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}.
References: Schulze-Pillot's paper on "An algorithm for computing genera of ternary and quaternary quadratic forms", p138. Donaldson's 1979 paper "Minkowski Reduction of Integral Matrices", p203.
EXAMPLES::
sage: Q = QuadraticForm(ZZ,4,[30,17,11,12,29,25,62,64,25,110]) sage: Q Quadratic form in 4 variables over Integer Ring with coefficients: [ 30 17 11 12 ] [ * 29 25 62 ] [ * * 64 25 ] [ * * * 110 ] sage: Q.minkowski_reduction_for_4vars__SP() ( Quadratic form in 4 variables over Integer Ring with coefficients: [ 29 -17 25 4 ] [ * 30 -11 5 ] [ * * 64 0 ] [ * * * 77 ] , <BLANKLINE> [ 0 1 0 0] [ 1 0 0 -1] [ 0 0 1 0] [ 0 0 0 1] ) """
## Only allow 4-variable forms raise TypeError("Oops! The given quadratic form has " + str(n) + \ " != 4 variables. =|")
## Step 1: Begin the reduction
## Loop through possible shorter vectors #print " j_range = ", range(n-1, -1, -1) #print "j = ", j
## Reduce if a shorter vector is found #print "y = ", y, " e_j = ", e_j, "\n"
## Further n=4 computations ## SP's B = our self.matrix()/2 ## SP's A = coeff matrix of his B ## Here we compute the double of both and compare.
## Create the transformation matrix
## Perform the reduction and restart the loop #print "Q_before = ", Q
## DIAGNOSTIC #print "Q(y) = ", Q(y) #print "Q(e_j) = ", Q(e_j) #print "M_new = ", M_new #print "Q_after = ", Q
## Step 2: Order A by certain criteria
## Condition (a) else:
i_sum = sum([abs(Q[i,k]) for k in range(4) if k != i]) j_sum = sum([abs(Q[j,k]) for k in range(4) if k != j])
## Condition (b) if (i_sum > j_sum): Q.swap_variables(i,j,in_place=True) M_new = matrix(R,n,n) M_new[i,j] = -1 M_new[j,i] = 1 for r in range(4): if (r == i) or (r == j): M_new[r,r] = 0 else: M_new[r,r] = 1 M = M * M_new
elif (i_sum == j_sum): for k in [2,1,0]: ## TO DO: These steps are a little redundant... Q1 = Q.matrix()
c_flag = True for l in range(k+1,4): c_flag = c_flag and (abs(Q1[i,l]) == abs(Q1[j,l]))
## Condition (c) if c_flag and (abs(Q1[i,k]) > abs(Q1[j,k])): Q.swap_variables(i,j,in_place=True) M_new = matrix(R,n,n) M_new[i,j] = -1 M_new[j,i] = 1 for r in range(4): if (r == i) or (r == j): M_new[r,r] = 0 else: M_new[r,r] = 1 M = M * M_new
## Step 3: Order the signs else:
Q.multiply_variable(-1, i, in_place=True) M_new = matrix(R,n,n) for r in range(4): if r == i: M_new[r,r] = -1 else: M_new[r,r] = 1 M = M * M_new
## Test a row 1 sign change ((Q[1,3] < 0) or (Q[1,3] == 0 and Q[1,2] < 0) \ or (Q[1,3] == 0 and Q[1,2] == 0 and Q[1,1] < 0))): Q.multiply_variable(-1, i, in_place=True) M_new = matrix(R,n,n) for r in range(4): if r == i: M_new[r,r] = -1 else: M_new[r,r] = 1 M = M * M_new
((Q[2,3] < 0) or (Q[2,3] == 0 and Q[2,2] < 0) \ or (Q[2,3] == 0 and Q[2,2] == 0 and Q[2,1] < 0))): Q.multiply_variable(-1, i, in_place=True) M_new = matrix(R,n,n) for r in range(4): if r == i: M_new[r,r] = -1 else: M_new[r,r] = 1 M = M * M_new
## Return the results
|