예제 #1
0
def fix1_qcurve_flag(ec, verbose=False):
    """
    Update ec structure (from nfcurves collection) with the correct
    q_curves flag.  For degree >2 at present we only do trivial tests
    here which do not require any computation.
    """
    if ec['q_curve']:  # keep old True values
        return ec

    # Easy sufficient tests in all degrees
    qc = False
    if ec['cm']:
        qc = True
    elif all(c == '0' for c in ec['jinv'].split(",")[1:]):
        qc = True

    if qc:  # then we have just set it to True
        if ec['q_curve'] != qc:
            if verbose:
                print("{}: changing q_curve flag from {} to {}".format(
                    ec['label'], ec['q_curve'], qc))
        ec['q_curve'] = qc
        return ec

    # else if degree != 2 just replace possibly false negatives with '?'
    if ec['degree'] > 2:
        qc = '?'
        # if ec['q_curve'] != qc:
        #     print("{}: changing q_curve flag from {} to {}".format(ec['label'],ec['q_curve'],qc))
        ec['q_curve'] = qc
        return ec

    # else (degree 2 only for now) do the work (knowing that E does
    # not have CM and j(E) is not in Q)

    K = FIELD(ec['field_label'])
    sigma = K.K().galois_group()[1]
    # Compute the Q-curve flag from scratch

    N = ideal_from_string(K.K(), ec['conductor_ideal'])
    if sigma(N) != N:
        qc = False
    else:  # construct and check the curve
        ainvsK = parse_ainvs(K.K(), ec['ainvs'])
        E = EllipticCurve(ainvsK)
        qc = is_Q_curve(E)
    if ec['q_curve'] != qc:
        if verbose:
            print("{}: changing q_curve flag from {} to {}".format(
                ec['label'], ec['q_curve'], qc))
    ec['q_curve'] = qc
    return ec
예제 #2
0
def curves(line, verbose=False):
    r""" Parses one line from a curves file.  Returns the label and a dict
    containing fields with keys 'field_label', 'degree', 'signature',
    'abs_disc', 'label', 'short_label', conductor_label',
    'conductor_ideal', 'conductor_norm', 'iso_label', 'iso_nlabel',
    'number', 'ainvs', 'jinv', 'cm', 'q_curve', 'base_change',
    'torsion_order', 'torsion_structure', 'torsion_gens'; and (added
    May 2016): 'equation', 'local_data', 'non_min_p', 'minD'

    Input line fields (13):

    field_label conductor_label iso_label number conductor_ideal conductor_norm a1 a2 a3 a4 a6 cm base_change

    Sample input line:

    2.0.4.1 65.18.1 a 1 [65,18,1] 65 1,1 1,1 0,1 -1,1 -1,0 0 0
    """
    # Parse the line and form the full label:
    data = split(line)
    if len(data) != 13:
        print "line %s does not have 13 fields, skipping" % line
    field_label = data[0]  # string
    IQF_flag = field_label.split(".")[:2] == ['2', '0']
    K = nf_lookup(field_label) if IQF_flag else None
    conductor_label = data[1]  # string
    # convert label (does nothing except for imaginary quadratic)
    conductor_label = convert_conductor_label(field_label, conductor_label)
    iso_label = data[2]  # string
    iso_nlabel = numerify_iso_label(iso_label)  # int
    number = int(data[3])  # int
    short_class_label = "%s-%s" % (conductor_label, iso_label)
    short_label = "%s%s" % (short_class_label, str(number))
    class_label = "%s-%s" % (field_label, short_class_label)
    label = "%s-%s" % (field_label, short_label)

    conductor_ideal = data[4]  # string
    conductor_norm = int(data[5])  # int
    ainvs = ";".join(data[6:11])  # one string joining 5 NFelt strings
    cm = data[11]  # int or '?'
    if cm != '?':
        cm = int(cm)

    # Create the field and curve to compute the j-invariant:
    dummy, deg, sig, abs_disc = field_data(field_label)
    K = nf_lookup(field_label)
    #print("Field %s created, gen_name = %s" % (field_label,str(K.gen())))
    ainvsK = parse_ainvs(K, ainvs)  # list of K-elements
    E = EllipticCurve(ainvsK)
    #print("{} created with disc = {}, N(disc)={}".format(E,K.ideal(E.discriminant()).factor(),E.discriminant().norm().factor()))
    j = E.j_invariant()
    jinv = NFelt(j)
    if cm == '?':
        cm = get_cm(j)
        if cm:
            print "cm=%s for j=%s" % (cm, j)

    q_curve = data[12]  # 0, 1 or ?.  If unknown we'll determine this below.
    if q_curve in ['0', '1']:  # already set -- easy
        q_curve = bool(int(q_curve))
    else:
        try:
            q_curve = is_Q_curve(E)
        except NotImplementedError:
            q_curve = '?'

    # Here we should check that the conductor of the constructed curve
    # agrees with the input conductor.
    N = ideal_from_string(K, conductor_ideal)
    NE = E.conductor()
    if N == "wrong" or N != NE:
        print(
            "Wrong conductor ideal {} for label {}, using actual conductor {} instead"
            .format(conductor_ideal, label, NE))
        conductor_ideal = ideal_to_string(NE)
        N = NE

    # get torsion order, structure and generators:
    torgroup = E.torsion_subgroup()
    ntors = int(torgroup.order())
    torstruct = [int(n) for n in list(torgroup.invariants())]
    torgens = [point_string(P.element()) for P in torgroup.gens()]

    # get label of elliptic curve over Q for base_change cases (a
    # subset of Q-curves)

    if True:  # q_curve: now we have not precomputed Q-curve status
        # but still want to test for base change!
        if verbose:
            print("testing {} for base-change...".format(label))
        E1list = E.descend_to(QQ)
        if len(E1list):
            base_change = [cremona_to_lmfdb(E1.label()) for E1 in E1list]
            if verbose:
                print "%s is base change of %s" % (label, base_change)
        else:
            base_change = []
            # print "%s is a Q-curve, but not base-change..." % label
    else:
        base_change = []

    # NB if this is not a global minimal model then local_data may
    # include a prime at which we have good reduction.  This causes no
    # problems except that the bad_reduction_type is then None which
    # cannot be converted to an integer.  The bad reduction types are
    # coded as (Sage) integers in {-1,0,1}.
    local_data = [{
        'p':
        ideal_to_string(ld.prime()),
        'normp':
        str(ld.prime().norm()),
        'ord_cond':
        int(ld.conductor_valuation()),
        'ord_disc':
        int(ld.discriminant_valuation()),
        'ord_den_j':
        int(max(0, -(E.j_invariant().valuation(ld.prime())))),
        'red':
        None
        if ld.bad_reduction_type() == None else int(ld.bad_reduction_type()),
        'kod':
        web_latex(ld.kodaira_symbol()).replace('$', ''),
        'cp':
        int(ld.tamagawa_number())
    } for ld in E.local_data()]

    non_minimal_primes = [ideal_to_string(P) for P in E.non_minimal_primes()]
    minD = ideal_to_string(E.minimal_discriminant_ideal())

    edata = {
        'field_label': field_label,
        'degree': deg,
        'signature': sig,
        'abs_disc': abs_disc,
        'class_label': class_label,
        'short_class_label': short_class_label,
        'label': label,
        'short_label': short_label,
        'conductor_label': conductor_label,
        'conductor_ideal': conductor_ideal,
        'conductor_norm': conductor_norm,
        'iso_label': iso_label,
        'iso_nlabel': iso_nlabel,
        'number': number,
        'ainvs': ainvs,
        'jinv': jinv,
        'cm': cm,
        'q_curve': q_curve,
        'base_change': base_change,
        'torsion_order': ntors,
        'torsion_structure': torstruct,
        'torsion_gens': torgens,
        'equation': web_latex(E),
        'local_data': local_data,
        'minD': minD,
        'non_min_p': non_minimal_primes,
    }

    return label, edata
예제 #3
0
def check_Q_curves(field_label='2.2.5.1',
                   min_norm=0,
                   max_norm=None,
                   fix=False,
                   verbose=False):
    """Given a (quadratic) field label test all curves E over that field for being Q-curves.
    """
    query = {}
    query['field_label'] = field_label
    query['conductor_norm'] = {'$gte': int(min_norm)}
    if max_norm:
        query['conductor_norm']['$lte'] = int(max_norm)
    else:
        max_norm = 'infinity'
    cursor = nfcurves.find(query)
    # keep the curves and re-find them, else the cursor times out.
    curves = [ec['label'] for ec in cursor]
    ncurves = len(curves)
    print("Checking {} curves over field {}".format(ncurves, field_label))
    K = FIELD(field_label)
    sigma = K.K().galois_group()[1]
    bad1 = []
    bad2 = []
    count = 0
    for label in curves:
        count += 1
        if count % 1000 == 0:
            print("checked {} curves ({}%)".format(count,
                                                   100.0 * count / ncurves))
        ec = nfcurves.find_one({'label': label})
        assert label == ec['label']
        method = None
        # first check that j(E) is rational (no computation needed)
        jinv = ec['jinv']
        if all(c == '0' for c in jinv.split(",")[1:]):
            if verbose: print("{}: j in QQ".format(label))
            qc = True
            method = "j in Q"
        elif ec['cm']:
            if verbose: print("{}: CM".format(label))
            qc = True
            method = "CM"
        else:  # construct and check the conductor
            if verbose:
                print("{}: checking conductor".format(label))
            N = ideal_from_string(K.K(), ec['conductor_ideal'])
            if sigma(N) != N:
                qc = False
                method = "conductor"
            else:  # construct and check the curve
                if verbose:
                    print("{}: checking isogenies".format(label))
                ainvsK = parse_ainvs(K.K(), ec['ainvs'])
                E = EllipticCurve(ainvsK)
                qc = is_Q_curve(E)
                method = "isogenies"
        db_qc = ec['q_curve']
        if qc and not db_qc:
            print("Curve {} is a Q-curve (using {}) but database thinks not".
                  format(label, method))
            bad1 += [label]
        elif db_qc and not qc:
            print(
                "Curve {} is not a Q-curve (using {}) but database thinks it is"
                .format(label, method))
            bad2 += [label]
        else:
            if verbose:
                print("Curve {} OK (using {})".format(label, method))
    print(
        "{} curves in the database are incorrectly labelled as being Q-curves".
        format(len(bad2)))
    print(
        "{} curves in the database are incorrectly labelled as NOT being Q-curves"
        .format(len(bad1)))
    return bad1, bad2