Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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))