示例#1
0
def sqrt_poly(g):
    if g.degree() == 0:
        return sqrt(g[0])

    d = GCD(g, g.derivative(g.parent().gen()))
    sg = g // d
    return sg * sqrt_poly(g // sg**2)
示例#2
0
def Eval0(cur,fra):
    """
    perform the evaluation at the origin
    on the curve cur=0 of the rational
    function fra, where fra is the ordered
    list fra=[numerator,denominator]
    """
    x, y = cur.parent().gens()
    phi,eta = PrePol(cur)
    gcd = GCD([cur] + fra)
    if ZeroAtOrigin(gcd):
        raise ValueError,  "the numerator and denominator vanish identically"
    fr0 = [ff // gcd for ff in fra]
    while True:
        preva = [nn(0,0) for nn in fr0]
        if preva != [0,0]:
            return preva
        fr0 = [UnaSe(eta,phi,ff) for ff in fr0]
        gcd = GCD(fr0)
        fr0= [ff // gcd for ff in fr0]
示例#3
0
def validate_character(level, character):
    """Assumes level is a positive integer N, checks that 0<character<=N
    and gcd(character,N)=1.  Returns None if OK, else a suitable error
    message.
    """
    #print "validate_character(%s,%s)" % (level, character)
    if not isinstance(character,int):
        return "The character number should be an integer. You gave: %s" % character
    from sage.all import GCD
    if character <= 0 or character > level or GCD(level,character)!=1:
        return "The character number should be a positive integer less than or equal to and coprime to the level %s. You gave: %s" % (level, character)
    return 0
示例#4
0
def field_intersection_list(defining_polynomials):
    # try to just use discriminants of the first 1000 polynomials
    D = 0
    for f in defining_polynomials[:1000]:
        D = GCD(D, f.discriminant())
        if D == 1:
            return f.parent().gen()

    L = NumberField(defining_polynomials[0], 'a')
    for f in defining_polynomials:
        K = NumberField(f, 'b')
        # the 1st argument should be the 'smaller' field
        L = NumberField(field_intersection(L, K), 'a')

        if L.degree() == 1:
            return f.parent().gen()
    else:
        return polredabs(L.absolute_polynomial())
示例#5
0
    def make_E(self):
        coeffs = self.ainvs  # list of 5 lists of d strings
        self.ainvs = [self.field.parse_NFelt(x) for x in coeffs]
        self.latex_ainvs = web_latex(self.ainvs)
        from sage.schemes.elliptic_curves.all import EllipticCurve
        self.E = E = EllipticCurve(self.ainvs)
        self.equn = web_latex(E)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        N = E.conductor()
        self.cond = web_latex(N)
        self.cond_norm = web_latex(N.norm())
        if N.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
        else:
            self.fact_cond = web_latex_ideal_fact(N.factor())
        self.fact_cond_norm = web_latex(N.norm().factor())

        D = self.field.K().ideal(E.discriminant())
        self.disc = web_latex(D)
        self.disc_norm = web_latex(D.norm())
        if D.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
        else:
            self.fact_disc = web_latex_ideal_fact(D.factor())
        self.fact_disc_norm = web_latex(D.norm().factor())

        # Minimal model?
        #
        # All curves in the database should be given
        # by models which are globally minimal if possible, else
        # minimal at all but one prime.  But we do not rely on this
        # here, and the display should be correct if either (1) there
        # exists a global minimal model but this model is not; or (2)
        # this model is non-minimal at more than one prime.
        #
        self.non_min_primes = non_minimal_primes(E)
        self.is_minimal = (len(self.non_min_primes) == 0)
        self.has_minimal_model = True
        if not self.is_minimal:
            self.non_min_prime = ','.join(
                [web_latex(P) for P in self.non_min_primes])
            self.has_minimal_model = has_global_minimal_model(E)

        if not self.is_minimal:
            Dmin = minimal_discriminant_ideal(E)
            self.mindisc = web_latex(Dmin)
            self.mindisc_norm = web_latex(Dmin.norm())
            if Dmin.norm(
            ) == 1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
            else:
                self.fact_mindisc = web_latex_ideal_fact(Dmin.factor())
            self.fact_mindisc_norm = web_latex(Dmin.norm().factor())

        j = E.j_invariant()
        if j:
            d = j.denominator()
            n = d * j  # numerator exists for quadratic fields only!
            g = GCD(list(n))
            n1 = n / g
            self.j = web_latex(n1)
            if d != 1:
                if n1 > 1:
                    #self.j = "("+self.j+")\(/\)"+web_latex(d)
                    self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d))
                else:
                    self.j = web_latex(d)
                if g > 1:
                    if n1 > 1:
                        self.j = web_latex(g) + self.j
                    else:
                        self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        if j.is_zero():
            self.fact_j = web_latex(j)
        else:
            try:
                self.fact_j = web_latex(j.factor())
            except (ArithmeticError,
                    ValueError):  # if not all prime ideal factors principal
                pass

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm % 4 == 0:
                d4 = ZZ(self.cm) // 4
                self.End = "\(\Z[\sqrt{%s}]\)" % (d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm

        # Q-curve / Base change
        self.qc = "no"
        try:
            if self.q_curve:
                self.qc = "yes"
        except AttributeError:  # in case the db entry does not have this field set
            pass

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr == 0:
            self.tor_struct_pretty = "Trivial"
        if self.tr == 1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr == 2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(
                self.torsion_structure)
        torsion_gens = [
            E([self.field.parse_NFelt(x) for x in P])
            for P in self.torsion_gens
        ]
        self.torsion_gens = ",".join([web_latex(P) for P in torsion_gens])

        # Rank etc
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "not recorded"
#       if rank in self:
#            self.r = web_latex(self.rank)

# Local data
        self.local_data = []
        for p in N.prime_factors():
            self.local_info = E.local_data(p, algorithm="generic")
            self.local_data.append({
                'p':
                web_latex(p),
                'norm':
                web_latex(p.norm().factor()),
                'tamagawa_number':
                self.local_info.tamagawa_number(),
                'kodaira_symbol':
                web_latex(self.local_info.kodaira_symbol()).replace('$', ''),
                'reduction_type':
                self.local_info.bad_reduction_type(),
                'ord_den_j':
                max(0,
                    E.j_invariant().valuation(p)),
                'ord_mindisc':
                self.local_info.discriminant_valuation()
            })

        # URLs of self and related objects:
        self.urls = {}
        self.urls['curve'] = url_for(".show_ecnf",
                                     nf=self.field_label,
                                     conductor_label=self.conductor_label,
                                     class_label=self.iso_label,
                                     number=self.number)
        self.urls['class'] = url_for(".show_ecnf_isoclass",
                                     nf=self.field_label,
                                     conductor_label=self.conductor_label,
                                     class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor",
                                         nf=self.field_label,
                                         conductor_label=self.conductor_label)
        self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label)

        if self.field.is_real_quadratic():
            self.hmf_label = "-".join(
                [self.field.label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage',
                                       field_label=self.field.label,
                                       label=self.hmf_label)

        if self.field.is_imag_quadratic():
            self.bmf_label = "-".join(
                [self.field.label, self.conductor_label, self.iso_label])

        self.friends = []
        self.friends += [('Isogeny class ' + self.short_class_label,
                          self.urls['class'])]
        if self.field.is_real_quadratic():
            self.friends += [('Hilbert Modular Form ' + self.hmf_label,
                              self.urls['hmf'])]
        if self.field.is_imag_quadratic():
            self.friends += [
                ('Bianchi Modular Form %s not yet available' % self.bmf_label,
                 '')
            ]

        self.properties = [('Base field', self.field.field_pretty()),
                           ('Label', self.label)]

        # Plot
        n1 = len(E.base_field().embeddings(RR))
        if (n1):
            self.plot = encode_plot(EC_nf_plot(E, self.field.generator_name()))
            self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
            self.properties += [(None, self.plot_link)]

        self.properties += [('Conductor', self.cond),
                            ('Conductor norm', self.cond_norm),
                            ('j-invariant', self.j), ('CM', self.cm_bool)]

        if self.base_change:
            self.properties += [
                ('base-change',
                 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))
            ]
        else:
            self.base_change = []  # in case it was False instead of []
            self.properties += [('Q-curve', self.qc)]

        self.properties += [
            ('Torsion order', self.ntors),
            ('Rank', self.rk),
        ]

        for E0 in self.base_change:
            self.friends += [('Base-change of %s /\(\Q\)' % E0,
                              url_for("ec.by_ec_label", label=E0))]
示例#6
0
    def make_E(self):
        coeffs = self.ainvs  # list of 5 lists of d strings
        self.ainvs = [self.field.parse_NFelt(x) for x in coeffs]
        self.latex_ainvs = web_latex(self.ainvs)
        from sage.schemes.elliptic_curves.all import EllipticCurve
        self.E = E = EllipticCurve(self.ainvs)
        self.equn = web_latex(E)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        N = E.conductor()
        self.cond = web_latex(N)
        self.cond_norm = web_latex(N.norm())
        if N.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
        else:
            self.fact_cond = web_latex_ideal_fact(N.factor())
        self.fact_cond_norm = web_latex(N.norm().factor())

        D = self.field.K().ideal(E.discriminant())
        self.disc = web_latex(D)
        self.disc_norm = web_latex(D.norm())
        if D.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
        else:
            self.fact_disc = web_latex_ideal_fact(D.factor())
        self.fact_disc_norm = web_latex(D.norm().factor())

        # Minimal model?
        #
        # All curves in the database should be given
        # by models which are globally minimal if possible, else
        # minimal at all but one prime.  But we do not rely on this
        # here, and the display should be correct if either (1) there
        # exists a global minimal model but this model is not; or (2)
        # this model is non-minimal at more than one prime.
        #
        self.non_min_primes = non_minimal_primes(E)
        self.is_minimal = (len(self.non_min_primes) == 0)
        self.has_minimal_model = True
        if not self.is_minimal:
            self.non_min_prime = ','.join(
                [web_latex(P) for P in self.non_min_primes])
            self.has_minimal_model = has_global_minimal_model(E)

        if not self.is_minimal:
            Dmin = minimal_discriminant_ideal(E)
            self.mindisc = web_latex(Dmin)
            self.mindisc_norm = web_latex(Dmin.norm())
            if Dmin.norm(
            ) == 1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
            else:
                self.fact_mindisc = web_latex_ideal_fact(Dmin.factor())
            self.fact_mindisc_norm = web_latex(Dmin.norm().factor())

        j = E.j_invariant()
        if j:
            d = j.denominator()
            n = d * j  # numerator exists for quadratic fields only!
            g = GCD(list(n))
            n1 = n / g
            self.j = web_latex(n1)
            if d != 1:
                if n1 > 1:
                    # self.j = "("+self.j+")\(/\)"+web_latex(d)
                    self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d))
                else:
                    self.j = web_latex(d)
                if g > 1:
                    if n1 > 1:
                        self.j = web_latex(g) + self.j
                    else:
                        self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        # See issue 1258: some j factorizations work bu take too long (e.g. EllipticCurve/6.6.371293.1/1.1/a/1)
        # If these are really wanted, they could be precomputed and stored in the db
        if j.is_zero():
            self.fact_j = web_latex(j)
        else:
            if self.field.K().degree(
            ) < 3:  #j.numerator_ideal().norm()<1000000000000:
                try:
                    self.fact_j = web_latex(j.factor())
                except (ArithmeticError, ValueError
                        ):  # if not all prime ideal factors principal
                    pass

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm % 4 == 0:
                d4 = ZZ(self.cm) // 4
                self.End = "\(\Z[\sqrt{%s}]\)" % (d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm
            # The line below will need to change once we have curves over non-quadratic fields
            # that contain the Hilbert class field of an imaginary quadratic field
            if self.signature == [0, 1] and ZZ(
                    -self.abs_disc * self.cm).is_square():
                self.ST = '<a href="%s">$%s$</a>' % (url_for(
                    'st.by_label', label='1.2.U(1)'), '\\mathrm{U}(1)')
            else:
                self.ST = '<a href="%s">$%s$</a>' % (url_for(
                    'st.by_label', label='1.2.N(U(1))'), 'N(\\mathrm{U}(1))')
        else:
            self.ST = '<a href="%s">$%s$</a>' % (url_for(
                'st.by_label', label='1.2.SU(2)'), '\\mathrm{SU}(2)')

        # Q-curve / Base change
        self.qc = "no"
        try:
            if self.q_curve:
                self.qc = "yes"
        except AttributeError:  # in case the db entry does not have this field set
            pass

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr == 0:
            self.tor_struct_pretty = "Trivial"
        if self.tr == 1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr == 2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(
                self.torsion_structure)
        torsion_gens = [
            E([self.field.parse_NFelt(x) for x in P])
            for P in self.torsion_gens
        ]
        self.torsion_gens = ",".join([web_latex(P) for P in torsion_gens])

        # Rank or bounds
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.rank_bounds)
        except AttributeError:
            self.rank_bounds = [0, Infinity]
            self.rk_bnds = "not available"

        # Generators
        try:
            gens = [
                E([self.field.parse_NFelt(x) for x in P]) for P in self.gens
            ]
            self.gens = ", ".join([web_latex(P) for P in gens])
            if self.rk == "?":
                self.reg = "not available"
            else:
                if gens:
                    self.reg = E.regulator_of_points(gens)
                else:
                    self.reg = 1  # otherwise we only get 1.00000...

        except AttributeError:
            self.gens = "not available"
            self.reg = "not available"
            try:
                if self.rank == 0:
                    self.reg = 1
            except AttributeError:
                pass

        # Local data
        self.local_data = []
        for p in N.prime_factors():
            self.local_info = E.local_data(p, algorithm="generic")
            self.local_data.append({
                'p':
                web_latex(p),
                'norm':
                web_latex(p.norm().factor()),
                'tamagawa_number':
                self.local_info.tamagawa_number(),
                'kodaira_symbol':
                web_latex(self.local_info.kodaira_symbol()).replace('$', ''),
                'reduction_type':
                self.local_info.bad_reduction_type(),
                'ord_den_j':
                max(0, -E.j_invariant().valuation(p)),
                'ord_mindisc':
                self.local_info.discriminant_valuation(),
                'ord_cond':
                self.local_info.conductor_valuation()
            })

        # URLs of self and related objects:
        self.urls = {}
        # It's useful to be able to use this class out of context, when calling url_for will fail:
        try:
            self.urls['curve'] = url_for(".show_ecnf",
                                         nf=self.field_label,
                                         conductor_label=quote(
                                             self.conductor_label),
                                         class_label=self.iso_label,
                                         number=self.number)
        except RuntimeError:
            return
        self.urls['class'] = url_for(".show_ecnf_isoclass",
                                     nf=self.field_label,
                                     conductor_label=quote(
                                         self.conductor_label),
                                     class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor",
                                         nf=self.field_label,
                                         conductor_label=quote(
                                             self.conductor_label))
        self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label)

        sig = self.signature
        real_quadratic = sig == [2, 0]
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0, 1]

        if totally_real:
            self.hmf_label = "-".join(
                [self.field.label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage',
                                       field_label=self.field.label,
                                       label=self.hmf_label)
            self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page",
                                             field=self.field_label,
                                             label=self.hmf_label,
                                             character='0',
                                             number='0')

        if imag_quadratic:
            self.bmf_label = "-".join(
                [self.field.label, self.conductor_label, self.iso_label])

        self.friends = []
        self.friends += [('Isogeny class ' + self.short_class_label,
                          self.urls['class'])]
        self.friends += [('Twists',
                          url_for('ecnf.index',
                                  field_label=self.field_label,
                                  jinv=self.jinv))]
        if totally_real:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label,
                              self.urls['hmf'])]
            self.friends += [('L-function', self.urls['Lfunction'])]
        if imag_quadratic:
            self.friends += [
                ('Bianchi Modular Form %s not available' % self.bmf_label, '')
            ]

        self.properties = [('Base field', self.field.field_pretty()),
                           ('Label', self.label)]

        # Plot
        if E.base_field().signature()[0]:
            self.plot = encode_plot(EC_nf_plot(E, self.field.generator_name()))
            self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
            self.properties += [(None, self.plot_link)]

        self.properties += [
            ('Conductor', self.cond),
            ('Conductor norm', self.cond_norm),
            # See issue #796 for why this is hidden
            # ('j-invariant', self.j),
            ('CM', self.cm_bool)
        ]

        if self.base_change:
            self.properties += [
                ('base-change',
                 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))
            ]
        else:
            self.base_change = []  # in case it was False instead of []
            self.properties += [('Q-curve', self.qc)]

        r = self.rk
        if r == "?":
            r = self.rk_bnds
        self.properties += [
            ('Torsion order', self.ntors),
            ('Rank', r),
        ]

        for E0 in self.base_change:
            self.friends += [('Base-change of %s /\(\Q\)' % E0,
                              url_for("ec.by_ec_label", label=E0))]

        self._code = None  # will be set if needed by get_code()
示例#7
0
    def prelabel(self):
        # this also sets:
        # - nu_*
        # - mu_*
        # and updates:
        # - gamma_factors

        def CCtuple(z):
            return (z.real(), z.imag().abs(), z.imag())

        def spectral_str(x, conjugate=False):
            if conjugate:
                assert x <= 0
                x = -x
                res = "c"
            elif x < 0:
                x = -x
                res = "m"
            else:
                res = "p"
            if x == 0:
                res += "0"
            else:
                res += "%.2f" % x
            return res

        GR, GC = self.gamma_factors
        GR = [elt + self.analytic_normalization for elt in GR]
        GC = [elt + self.analytic_normalization for elt in GC]
        b, e = self.conductor.perfect_power()
        if e == 1:
            conductor = b
        else:
            conductor = "{}e{}".format(b, e)
        beginning = "-".join(map(str, [self.degree, conductor, self.central_character]))

        GRcount = Counter(GR)
        GCcount = Counter(GC)
        # convert gamma_R to gamma_C
        for x in sorted(GRcount):
            shift = min(GRcount[x], GRcount[x+1])
            if shift:
                # We store the real parts of nu doubled
                GCcount[x] += shift
                GRcount[x] -= shift
                GRcount[x] -= shift
        GR = sum([[m]*c for m, c in GRcount.items()], [])
        GC = sum([[m]*c for m, c in GCcount.items()], [])
        assert self.degree == len(GR) + 2*len(GC)
        GR.sort(key=CCtuple)
        GC.sort(key=CCtuple)

        self.mu_imag = [elt.imag() for elt in GR]
        self.nu_imag = [elt.imag() for elt in GC]

        # deal with real parts
        GR_real = [elt.real() for elt in GR]
        GC_real = [elt.real() for elt in GC]
        self.mu_real = [x.round() for x in GR_real]
        assert set(self.mu_real).issubset(set([0,1]))
        self.nu_real_doubled = [(2*x).round() for x in GC_real]
        GRcount = Counter(GR_real)
        GCcount = Counter(GC_real)
        ge = GCD(GCD(list(GRcount.values())), GCD(list(GCcount.values())))
        if ge > 1:
            GR_real = sum(([k]*(v//ge) for k, v in GRcount.items()), [])
            GC_real = sum(([k]*(v//ge) for k, v in GCcount.items()), [])

        rs = ''.join(['r%d' % elt.real().round() for elt in GR_real])
        cs = ''.join(['c%d' % (elt.real()*2).round() for elt in GC_real])
        gammas = "-" + rs + cs
        if ge > 1:
            gammas += "e%d" % ge
        if self.algebraic:
            end = "-0"
        else:
            end = "-"
            for G in [GR, GC]:
                for i, elt in enumerate(G):
                    conjugate = False
                    if elt.imag() <= 0 and i < len(G) - 1 and elt.conjugate() == G[i + 1]:
                        conjugate = True
                    elif elt.imag() >= 0 and i > 0 and elt.conjugate() == G[i - 1]:
                        # we already listed this one as a conjugate
                        continue
                    end += spectral_str(elt.imag(), conjugate=conjugate)
        # these are stored in algebraic normalization
        self.gamma_factors = [[elt -  self.analytic_normalization for elt in G]
                              for G in [GR, GC]]
        self.spectral_label = gammas + end
        return beginning + gammas + end
示例#8
0
def field_intersection_matrix(matrix_defining_polynomials):
    r"""
    INPUT:

        - a matrix of polynomials defining numberfields (f_ij)

    OUTPUT:

        - returns a pair per column entry (Ak, Bk)
            after picking a row with a small intersection, WLOG i = 0
            Let S_ij denote all the polynomials defining subfields of QQ[x]/fij

            Then Bk = S_0k \cap (\cap_{i > 0) \cup_j S_ij)
            If the list Bk can be obtained as list of subfields of one subfield
            then such subfield, otherwise Ak is None


    """
    if len(matrix_defining_polynomials[0]) == 1:
        f = field_intersection_list(
            [elt[0] for elt in matrix_defining_polynomials])
        return [[f, subfields_polynomials(f)]]

    # we would like to pick the row which has the smallest intersection
    # an easy to get something close to that,is by picking the one with
    # lowest GCD of the discriminants
    Di = None
    Dmin = None
    for i, row in enumerate(matrix_defining_polynomials):
        D = GCD([elt.discriminant() for elt in row])
        if Dmin is None or D < Dmin:
            Dmin = D
            Di = i
        if Dmin == 1:
            break

    working_row = matrix_defining_polynomials[Di]

    subfields_matrix = [None] * len(matrix_defining_polynomials)
    output = [None] * len(working_row)
    for k, f in enumerate(working_row):
        Lsubfields = Set(subfields_polynomials(f))
        for i, row in enumerate(matrix_defining_polynomials):
            if i != Di:
                if subfields_matrix[i] is None:
                    U = Set([])
                    for g in row:
                        Sg = Set(subfields_polynomials(g))
                        U = U.union(Sg)
                    subfields_matrix[i] = U
                # try to discard some subfields
                Lsubfields = Lsubfields.intersection(subfields_matrix[i])
                if Lsubfields.cardinality() == 1:
                    # QQ is the only possible subfield
                    break

        Lsubfields = list(Lsubfields)
        Lsubfields.sort()
        output[k] = [None, Lsubfields]
        # try to produce a single polynomial, if Lsubfields are all the subfields of a common subfield
        if len(Lsubfields) == 1:
            output[k][0] = f.parent().gen()
        else:
            if Lsubfields[-1].degree() != Lsubfields[-2].degree():
                # there is one field of maximal degree, that might contain all the others
                K = NumberField(Lsubfields[-1], 'a')
                maxsubfields = [
                    polredabs(sK.absolute_polynomial())
                    for sK, _, _ in K.subfields()
                ]
                if maxsubfields == Lsubfields:
                    output[k][0] = Lsubfields[-1]

    return output
示例#9
0
def make_label(L, normalized=False):
    GR, GC = L['gamma_factors']
    analytic_normalization = 0 if normalized else L['motivic_weight']/2
    GR = [CDF(elt) + analytic_normalization for elt in GR]
    GC = [CDF(elt) + analytic_normalization for elt in GC]
    b, e = L['conductor'].perfect_power()
    if e == 1:
        conductor = b
    else:
        conductor = "{}e{}".format(b, e)
    beginning = "-".join(map(str, [L['degree'], conductor, L['central_character']]))

    GRcount = Counter(GR)
    GCcount = Counter(GC)
    # convert gamma_R to gamma_C
    zero = LmfdbRealLiteral(RR, '0')
    one = LmfdbRealLiteral(RR, '1')
    while GRcount[zero] > 0 and GRcount[one] > 0:
        GCcount[zero] += 1
        GRcount[zero] -= 1
        GRcount[one] -= 1
    GR = sum([[m]*c for m, c in GRcount.items()], [])
    GC = sum([[m]*c for m, c in GCcount.items()], [])
    assert L['degree'] == len(GR) + 2*len(GC)
    GR.sort(key=CCtuple)
    GC.sort(key=CCtuple)

    L["mu_imag"] = [elt.imag() for elt in GR]
    L["nu_imag"] = [elt.imag() for elt in GC]

    # deal with real parts
    GR_real = [elt.real() for elt in GR]
    GC_real = [elt.real() for elt in GC]
    L["mu_real"] = [x.round() for x in GR_real]
    assert set(L["mu_real"]).issubset(set([0,1]))
    L["nu_real_doubled"] = [(2*x).round() for x in GC_real]
    GRcount = Counter(GR_real)
    GCcount = Counter(GC_real)
    ge = GCD(GCD(list(GRcount.values())), GCD(list(GCcount.values())))
    if ge > 1:
        GR_real = sum(([k]*(v//ge) for k, v in GRcount.items()), [])
        GC_real = sum(([k]*(v//ge) for k, v in GCcount.items()), [])

    rs = ''.join(['r%d' % elt.real().round() for elt in GR_real])
    cs = ''.join(['c%d' % (elt.real()*2).round() for elt in GC_real])
    gammas = "-" + rs + cs
    if ge > 1:
        gammas += "e%d" % ge
    if L['algebraic']:
        end = "-0"
    else:
        end = "-"
        for G in [GR, GC]:
            for i, elt in enumerate(G):
                conjugate = False
                if elt.imag() <= 0 and i < len(G) - 1 and elt.conjugate() == G[i + 1]:
                    conjugate = True
                elif elt.imag() >= 0 and i > 0 and elt.conjugate() == G[i - 1]:
                    # we already listed this one as a conjugate
                    continue
                end += spectral_str(elt.imag(), conjugate=conjugate)
    L["prelabel"] = beginning + gammas + end
    return tuple(GR), tuple(GC)