def __init__(self, F, m, B, a=None): r""" Initialization routine (constructor). INPUT: - ``F`` -- number field, the base field - ``m`` -- integer, the relative degree - ``B`` -- integer, the discriminant bound - ``a`` -- list (default: []), the coefficient list to begin with, corresponding to ``a[len(a)]*x^n + ... + a[0]x^(n-len(a))``. OUTPUT: the data initialized to begin enumeration of totally real fields with base field F, degree n, discriminant bounded by B, and starting with coefficients a. EXAMPLES:: sage: F.<t> = NumberField(x^2-2) sage: T = sage.rings.number_field.totallyreal_rel.tr_data_rel(F, 2, 2000) """ if a is None: # don't make the stupid noob mistake of putting a=[] a = [] # in the function signature above. # Initialize constants. self.m = m d = F.degree() self.d = d self.n = m*d self.B = B self.gamma = hermite_constant(self.n-self.d) self.F = F self.Z_F = F.maximal_order() self.Foo = F.real_embeddings() self.dF = abs(F.disc()) self.Fx = PolynomialRing(F, 'xF') self.beta = [[]]*m self.gnk = [[]]*m self.trace_elts = [] Z_Fbasis = self.Z_F.basis() # Initialize variables. if a == []: # No starting input, all polynomials will be found; initialize to zero. self.a = [0]*m + [1] self.amaxvals = [[]]*m anm1s = [[i] for i in range(0,m//2+1)] for i in range(1,self.d): for j in range(len(anm1s)): anm1s[j] = [ anm1s[j] + [i] for i in range(m)] anm1s = sum(anm1s, []) anm1s = [sum([Z_Fbasis[i]*a[i] for i in range(self.d)]) for a in anm1s] # Minimize trace in class. import numpy for i in range(len(anm1s)): Q = [ [ v(m*x) for v in self.Foo] + [0] for x in Z_Fbasis] + [[v(anm1s[i]) for v in self.Foo] + [10**6]] pari_string = '['+';'.join([','.join(["%s"%ii for ii in row]) for row in zip(*Q)])+']' adj = pari(pari_string).qflll()[self.d] anm1s[i] += sum([m*Z_Fbasis[ii]*int(adj[ii])//int(adj[self.d]) for ii in range(self.d)]) self.amaxvals[m-1] = anm1s self.a[m-1] = self.amaxvals[m-1].pop() self.k = m-2 bl = math.ceil(1.7719*self.n) br = max([1./m*(am1**2).trace() + \ self.gamma*(1./(m**d)*self.B/self.dF)**(1./(self.n-d)) for am1 in anm1s]) br = math.floor(br) T2s = self.F._positive_integral_elements_with_trace([bl,br]) self.trace_elts.append([bl,br,T2s]) elif len(a) <= m+1: # First few coefficients have been specified. # The value of k is the largest index of the coefficients of a which is # currently unknown; e.g., if k == -1, then we can iterate # over polynomials, and if k == n-1, then we have finished iterating. if a[len(a)-1] != 1: raise ValueError, "a[len(a)-1](=%s) must be 1 so polynomial is monic"%a[len(a)-1] raise NotImplementedError, "These have not been checked." k = m-len(a) self.k = k a = [0]*(k+1) + a self.amaxvals = [[]]*m for i in range(0,n+1): self.a[i] = a[i] # Bounds come from an application of Lagrange multipliers in degrees 2,3. self.b_lower = [-1./m*(v(self.a[m-1]) + (m-1.)*math.sqrt(v(self.a[m-1])**2 - 2.*(1+1./(m-1))*v(self.a[m-2]))) for v in self.Foo] self.b_upper = [-1./m*(v(self.a[m-1]) - (m-1.)*math.sqrt(v(self.a[m-1])**2 - 2.*(1+1./(m-1))*v(self.a[m-2]))) for v in self.Foo] if k < m-2: bminmax = [lagrange_degree_3(n,v(self.a[m-1]),v(self.a[m-2]),v(self.a[m-3])) for v in self.Foo] self.b_lower = bminmax[0] self.b_upper = bminmax[1] # Annoying, but must reverse coefficients for numpy. gnk = [binomial(j,k+2)*a[j] for j in range(k+2,n+1)] self.beta[k+1] = [[self.b_lower] + numpy.roots([v(gnk[i]) for i in range(len(gnk))].reverse()).tolist().sort() + [self.b_upper] for v in self.Foo] # Now to really initialize gnk. self.gnk[k+1] = [[0] + [binomial(j,k+1)*v(a[j]) for j in range (k+2,m+1)] for v in self.Foo] else: # Bad input! raise ValueError, "a has length %s > m+1"%len(a)
def __init__(self, F, m, B, a=None): r""" Initialization routine (constructor). INPUT: - ``F`` -- number field, the base field - ``m`` -- integer, the relative degree - ``B`` -- integer, the discriminant bound - ``a`` -- list (default: []), the coefficient list to begin with, corresponding to ``a[len(a)]*x^n + ... + a[0]x^(n-len(a))``. OUTPUT: the data initialized to begin enumeration of totally real fields with base field F, degree n, discriminant bounded by B, and starting with coefficients a. EXAMPLES:: sage: F.<t> = NumberField(x^2-2) sage: T = sage.rings.number_field.totallyreal_rel.tr_data_rel(F, 2, 2000) """ if a is None: # don't make the stupid noob mistake of putting a=[] a = [] # in the function signature above. # Initialize constants. self.m = m d = F.degree() self.d = d self.n = m*d self.B = B self.gamma = hermite_constant(self.n-self.d) self.F = F self.Z_F = F.maximal_order() self.Foo = F.real_embeddings() self.dF = abs(F.disc()) self.Fx = PolynomialRing(F, 'xF') self.beta = [[]]*m self.gnk = [[]]*m self.trace_elts = [] Z_Fbasis = self.Z_F.basis() # Initialize variables. if a == []: # No starting input, all polynomials will be found; initialize to zero. self.a = [0]*m + [1] self.amaxvals = [[]]*m anm1s = [[i] for i in range(0,m//2+1)] for i in range(1,self.d): for j in range(len(anm1s)): anm1s[j] = [ anm1s[j] + [i] for i in range(m)] anm1s = sum(anm1s, []) anm1s = [sum([Z_Fbasis[i]*a[i] for i in range(self.d)]) for a in anm1s] # Minimize trace in class. import numpy for i in range(len(anm1s)): Q = [ [ v(m*x) for v in self.Foo] + [0] for x in Z_Fbasis] + [[v(anm1s[i]) for v in self.Foo] + [10**6]] pari_string = '['+';'.join([','.join(["%s"%ii for ii in row]) for row in zip(*Q)])+']' adj = pari(pari_string).qflll()[self.d] anm1s[i] += sum([m*Z_Fbasis[ii]*int(adj[ii])//int(adj[self.d]) for ii in range(self.d)]) self.amaxvals[m-1] = anm1s self.a[m-1] = self.amaxvals[m-1].pop() self.k = m-2 bl = math.ceil(1.7719*self.n) br = max([1./m*(am1**2).trace() + \ self.gamma*(1./(m**d)*self.B/self.dF)**(1./(self.n-d)) for am1 in anm1s]) br = math.floor(br) T2s = self.F._positive_integral_elements_with_trace([bl,br]) self.trace_elts.append([bl,br,T2s]) elif len(a) <= m+1: # First few coefficients have been specified. # The value of k is the largest index of the coefficients of a which is # currently unknown; e.g., if k == -1, then we can iterate # over polynomials, and if k == n-1, then we have finished iterating. if a[len(a)-1] != 1: raise ValueError("a[len(a)-1](=%s) must be 1 so polynomial is monic"%a[len(a)-1]) raise NotImplementedError("These have not been checked.") k = m-len(a) self.k = k a = [0]*(k+1) + a self.amaxvals = [[]]*m for i in range(0,n+1): self.a[i] = a[i] # Bounds come from an application of Lagrange multipliers in degrees 2,3. self.b_lower = [-1./m*(v(self.a[m-1]) + (m-1.)*math.sqrt(v(self.a[m-1])**2 - 2.*(1+1./(m-1))*v(self.a[m-2]))) for v in self.Foo] self.b_upper = [-1./m*(v(self.a[m-1]) - (m-1.)*math.sqrt(v(self.a[m-1])**2 - 2.*(1+1./(m-1))*v(self.a[m-2]))) for v in self.Foo] if k < m-2: bminmax = [lagrange_degree_3(n,v(self.a[m-1]),v(self.a[m-2]),v(self.a[m-3])) for v in self.Foo] self.b_lower = bminmax[0] self.b_upper = bminmax[1] # Annoying, but must reverse coefficients for numpy. gnk = [binomial(j,k+2)*a[j] for j in range(k+2,n+1)] self.beta[k+1] = [[self.b_lower] + numpy.roots([v(gnk[i]) for i in range(len(gnk))].reverse()).tolist().sort() + [self.b_upper] for v in self.Foo] # Now to really initialize gnk. self.gnk[k+1] = [[0] + [binomial(j,k+1)*v(a[j]) for j in range (k+2,m+1)] for v in self.Foo] else: # Bad input! raise ValueError("a has length %s > m+1"%len(a))