Ticket #11474: trac11474_unique_elliptic_curves.patch

File trac11474_unique_elliptic_curves.patch, 24.4 KB (added by SimonKing, 9 years ago)

Make elliptic curves unique parents -- doesn't work yet

  • sage/databases/cremona.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1308143960 -7200
    # Node ID 04a9733fad370341cea1483eb565bdcaaeef4aac
    # Parent  fb00ec75853019eb9799fd863b193fe82ee97c74
    #11474: Make elliptic curves unique parents.
    
    diff --git a/sage/databases/cremona.py b/sage/databases/cremona.py
    a b  
    694694                message = "There is no elliptic curve with label "+label+" in the currently available databases"
    695695            raise RuntimeError, message
    696696       
    697         F = elliptic.EllipticCurve(e[0])
     697        from sage.all import QQ
     698        from sage.structure.sequence import Sequence
     699        from sage.schemes.elliptic_curves.ell_rational_field import EllipticCurve_rational_field
     700        #F = elliptic.EllipticCurve(e[0])
     701        F = EllipticCurve_rational_field.__new__(EllipticCurve_rational_field)
     702        EllipticCurve_rational_field.__init__(F, QQ,
     703                                              Sequence(e[0],universe=QQ,immutable=True))
    698704        F._set_cremona_label("%s %s %s"%(N, iso, num))
    699705        F._set_rank(e[1])
    700706        F._set_torsion_order(e[2])
  • sage/schemes/elliptic_curves/constructor.py

    diff --git a/sage/schemes/elliptic_curves/constructor.py b/sage/schemes/elliptic_curves/constructor.py
    a b  
    66- William Stein (2005): Initial version
    77
    88- John Cremona (2008-01): EllipticCurve(j) fixed for all cases
     9
     10- Simon King (2011-06): Make elliptic curves unique parents (trac ticket #11474)
    911"""
    1012
    1113#*****************************************************************************
     
    6365      or ``EllipticCurve(j=j)`` instead.         
    6466
    6567   
    66     EXAMPLES: We illustrate creating elliptic curves.
    67    
     68    EXAMPLES:
     69
     70    We illustrate creating elliptic curves.
    6871    ::
    6972   
    7073        sage: EllipticCurve([0,0,1,-1,0])
    7174        Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
     75        sage: EllipticCurve([0,0,1,-1,0]) is EllipticCurve([0,0,1,-1,0])
     76        True
    7277   
    7378    We create a curve from a Cremona label::
    7479   
    7580        sage: EllipticCurve('37b2')
    7681        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
    77         sage: EllipticCurve('5077a')
     82        sage: E = EllipticCurve('5077a'); E
    7883        Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
    79         sage: EllipticCurve('389a')
    80         Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
     84
     85    Note that elliptic curves almost are unique parent structures, by trac
     86    ticket #11461: Two elliptic curves have equal `a`-invariants and are defined
     87    over the same field then they are not only equal but identical::
     88
     89        sage: E is EllipticCurve('5077a') is EllipticCurve(QQ, E.a_invariants()) is EllipticCurve(j = E.j_invariant())
     90        True
     91
     92    The only exception can occur if an elliptic curve is equal to a
     93    curve from the database: If an elliptic curve found in the cache
     94    has data that are different from the data provided by the
     95    database, then the two elliptic curves are equal but distinct::
     96
     97        sage: E = EllipticCurve([0, 1, 1, -2, 0])
     98        sage: E is EllipticCurve('389a')
     99        True
     100        sage: E._EllipticCurve_rational_field__cremona_label = 'bogus'
     101        sage: E is EllipticCurve('389a')
     102        False
     103        sage: E.label()
     104        'bogus'
     105        sage: EllipticCurve('389a').label()
     106        '389a1'
     107
     108    However, attributes that are provided by the database are
     109    automatically added to the curve found in the cache, if these
     110    attributes have not been previously assigned.
     111    ::
     112
     113        sage: del E._EllipticCurve_rational_field__cremona_label
     114        sage: E is EllipticCurve('389a')
     115        True
     116        sage: E._EllipticCurve_rational_field__cremona_label
     117        '389 a 1'
    81118   
    82119    We create curves over a finite field as follows::
    83120   
    84121        sage: EllipticCurve([GF(5)(0),0,1,-1,0])
    85122        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
    86         sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
    87         Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
     123
     124    The same object can be obtained by providing the data in a slightly
     125    different way::
     126
     127        sage: EllipticCurve([GF(5)(0),0,1,-1,0]) is EllipticCurve(GF(5), [0, 0,1,-1,0])
     128        True
    88129
    89130    Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
    90131    "elliptic curve over a finite field"::
    91132
    92133        sage: F = Zmod(101)
    93         sage: EllipticCurve(F, [2, 3])
     134        sage: E = EllipticCurve(F, [2, 3]); E
    94135        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
    95         sage: E = EllipticCurve([F(2), F(3)])
     136        sage: E is EllipticCurve([F(2), F(3)])
    96137        sage: type(E)
    97138        <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field'>
    98139           
     
    100141    are of type "generic elliptic curve"::
    101142
    102143        sage: F = Zmod(95)
    103         sage: EllipticCurve(F, [2, 3])
     144        sage: E = EllipticCurve(F, [2, 3]); E
    104145        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
    105         sage: E = EllipticCurve([F(2), F(3)])
     146        sage: E is EllipticCurve([F(2), F(3)])
     147        True
    106148        sage: type(E)
    107149        <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic'>
    108150   
     
    114156        sage: E.j_invariant()
    115157        2988.97297297297
    116158   
    117     We can also create elliptic curves by giving the Weierstrass equation::
     159    We can also create elliptic curves by giving the Weierstrass equation, and again
     160    we find that elliptic curves are unique::
    118161   
    119162        sage: x, y = var('x,y')
    120         sage: EllipticCurve(y^2 + y ==  x^3 + x - 9)
     163        sage: E = EllipticCurve(y^2 + y ==  x^3 + x - 9); E
    121164        Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field
    122        
     165        sage: E is EllipticCurve(E.base_ring(), E.a_invariants())
     166        True
    123167        sage: R.<x,y> = GF(5)[]
    124         sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
     168        sage: E = EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x); E
    125169        Elliptic Curve defined by y^2 + x*y  = x^3 + x^2 + 2 over Finite Field of size 5
     170        sage: E is EllipticCurve(E.base_ring(), E.a_invariants())
     171        True
    126172
    127     We can explicitly specify the `j`-invariant::
     173    We can explicitly specify the `j`-invariant, again in a unique way::
    128174
    129         sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
     175        sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.a_invariants(); E.label()
    130176        Elliptic Curve defined by y^2 = x^3 - x over Rational Field
    131177        1728
     178        (0, 0, 0, -1, 0)
    132179        '32a2'
     180        sage: E is EllipticCurve(E.base_ring(), E.a_invariants())
     181        True
     182        sage: E is EllipticCurve(E.label())
     183        True
     184        sage: E is EllipticCurve(j = E.j_invariant())
     185        True
     186
     187    ::
    133188
    134189        sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
    135190        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
    136191        2
     192        sage: E is EllipticCurve(E.base_ring(), E.a_invariants())
     193        True
    137194
    138195    See trac #6657::   
    139196
  • sage/schemes/elliptic_curves/ell_finite_field.py

    diff --git a/sage/schemes/elliptic_curves/ell_finite_field.py b/sage/schemes/elliptic_curves/ell_finite_field.py
    a b  
    4242import ell_point
    4343from sage.functions.all import log
    4444from sage.rings.arith import integer_ceil, integer_floor, gcd, lcm
    45 from sage.structure.sequence import Sequence
     45from sage.structure.sequence import Sequence, Sequence_generic
    4646
    4747import sage.plot.all as plot
    4848
     
    5353    """
    5454    Elliptic curve over a finite field.
    5555    """
    56     def __init__(self, x, y=None):
     56    @staticmethod
     57    def __classcall__(cls, x, y=None):
     58        """
     59        Preprocess arguments such as to obtain a unique descriptor.
     60
     61        TESTS::
     62
     63            sage: E = EllipticCurve(GF(101),[2,3])
     64            sage: type(E)
     65            <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field'>
     66            sage: E is EllipticCurve(E.base_ring(), E.a_invariants())  # indirect doctest
     67            True
     68
     69        """
     70        if y is None:
     71            if isinstance(x, Sequence_generic) and x.is_immutable():
     72                ainvs = x
     73            else:
     74                ainvs = Sequence(x, immutable=True)
     75        else:
     76            ainvs = Sequence(y, universe=x, immutable=True)
     77        return super(EllipticCurve_finite_field, cls).__classcall__(cls, ainvs.universe(), ainvs)
     78       
     79    def __init__(self, field, ainvs):
    5780        """
    5881        Special constructor for elliptic curves over a finite field
    5982       
     
    88111            sage: type(E)
    89112            <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic'>
    90113        """
    91         if isinstance(x, list):
    92             seq = Sequence(x)
    93         else:
    94             seq = Sequence(y, universe=x)
    95         ainvs = list(seq)
    96         field = seq.universe()
    97114        if not isinstance(field, ring.Ring):
    98115            raise TypeError
    99116
    100         EllipticCurve_field.__init__(self, ainvs)
     117        EllipticCurve_field.__init__(self, field, ainvs)
    101118
    102119        self._point_class = ell_point.EllipticCurvePoint_finite_field
    103120
  • sage/schemes/elliptic_curves/ell_generic.py

    diff --git a/sage/schemes/elliptic_curves/ell_generic.py b/sage/schemes/elliptic_curves/ell_generic.py
    a b  
    7777import weierstrass_morphism as wm
    7878from constructor import EllipticCurve
    7979
     80from sage.structure.sequence import Sequence, Sequence_generic
     81from sage.structure.unique_representation import UniqueRepresentation
    8082
    8183factor = arith.factor
    8284sqrt = math.sqrt
     
    104106    """
    105107    return isinstance(x, EllipticCurve_generic)
    106108
    107 class EllipticCurve_generic(plane_curve.ProjectiveCurve_generic):
     109class EllipticCurve_generic(UniqueRepresentation, plane_curve.ProjectiveCurve_generic):
    108110    r"""
    109111    Elliptic curve over a generic base ring.
    110112   
     
    119121        sage: -5*P
    120122        (179051/80089 : -91814227/22665187 : 1)
    121123    """
    122     def __init__(self, ainvs, extra=None):
     124    @staticmethod
     125    def __classcall__(cls, ainvs, extra=None):
     126        """
     127        Preprocess arguments such as to obtain a unique descriptor.
     128
     129        TESTS::
     130
     131            sage: E = EllipticCurve(IntegerModRing(91),[1,2,3,4,5])
     132            sage: type(E)
     133            <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic'>
     134            sage: E is EllipticCurve(E.base_ring(), E.a_invariants())  # indirect doctest
     135            True
     136
     137        """
     138        if extra != None:   # possibility of two arguments
     139            K, ainvs = ainvs, extra
     140        else:
     141            K = ainvs[0].parent()
     142        assert len(ainvs) == 2 or len(ainvs) == 5
     143        if len(ainvs) == 2:
     144            ainvs = [K(0),K(0),K(0)] + ainvs
     145        if not (isinstance(ainvs,Sequence_generic) and ainvs.is_immutable()):
     146            ainvs = Sequence(ainvs, universe=K, immutable=True)
     147        return super(EllipticCurve_generic,cls).__classcall__(cls, K, ainvs)
     148
     149    def __init__(self, K, ainvs):
    123150        r"""
    124151        Constructor from `a`-invariants (long or short Weierstrass coefficients).
    125152
    126153        INPUT:
    127154
    128         - ``ainvs`` (list) -- either `[a_1,a_2,a_3,a_4,a_6]` or
    129           `[a_4,a_6]` (with `a_1=a_2=a_3=0` in the second case).
     155        - ``ainvs`` (immutable Sequence) -- `[a_1,a_2,a_3,a_4,a_6]`
    130156
    131157        .. note::
    132158
     
    149175            sage: EllipticCurve(IntegerModRing(91),[1,2,3,4,5])
    150176            Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Ring of integers modulo 91
    151177        """
    152         if extra != None:   # possibility of two arguments
    153             K, ainvs = ainvs, extra
    154         else:
    155             K = ainvs[0].parent()
    156         assert len(ainvs) == 2 or len(ainvs) == 5
    157178        self.__base_ring = K
    158         ainvs = [K(x) for x in ainvs]
    159         if len(ainvs) == 2:
    160             ainvs = [K(0),K(0),K(0)] + ainvs
    161179        self.__ainvs = tuple(ainvs)
    162180        if self.discriminant() == 0:
    163181            raise ArithmeticError, \
  • sage/schemes/elliptic_curves/ell_number_field.py

    diff --git a/sage/schemes/elliptic_curves/ell_number_field.py b/sage/schemes/elliptic_curves/ell_number_field.py
    a b  
    111111from sage.rings.infinity import Infinity # just for verbose output
    112112from sage.rings.arith import valuation
    113113
     114from sage.structure.sequence import Sequence
     115
    114116class EllipticCurve_number_field(EllipticCurve_field):
    115117    r"""
    116118    Elliptic curve over a number field.
     
    121123        sage: EllipticCurve([i, i - 1, i + 1, 24*i + 15, 14*i + 35])
    122124        Elliptic Curve defined by y^2 + i*x*y + (i+1)*y = x^3 + (i-1)*x^2 + (24*i+15)*x + (14*i+35) over Number Field in i with defining polynomial x^2 + 1
    123125    """
    124     def __init__(self, x, y=None):
     126    @staticmethod
     127    def __classcall__(cls, x, y=None):
     128        """
     129        Preprocess arguments such as to obtain a unique descriptor.
     130
     131        TESTS::
     132
     133            sage: K.<i>=NumberField(x^2+1)
     134            sage: E = EllipticCurve([i, i - 1, i + 1, 24*i + 15, 14*i + 35])
     135            sage: E is EllipticCurve(E.base_ring(),E.a_invariants()) # indirect doctest
     136            True
     137
     138        """
     139        if y is None:
     140            if isinstance(x, (list,tuple)):
     141                field = x[0].parent()
     142                ainvs = Sequence(x, universe=field, immutable=True)
     143        else:
     144            if isinstance(y, str):
     145                field = x
     146                X = sage.databases.cremona.CremonaDatabase()[y]
     147                ainvs = Sequence(X.a_invariants(), universe=field, immutable=True)
     148            else:
     149                field = x
     150                ainvs = Sequence(y, universe=field, immutable=True)
     151        if not (isinstance(field, Ring)):
     152            raise TypeError, "Can not determine the ring for that elliptic curve"
     153        return super(EllipticCurve_number_field,cls).__classcall__(cls, field, ainvs)
     154
     155    def __init__(self, K, ainvs):
    125156        r"""
    126157        Allow some ways to create an elliptic curve over a number
    127158        field in addition to the generic ones.
     
    144175            Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 over Number Field in i with defining polynomial x^2 + 1
    145176
    146177        """
    147         if y is None:
    148             if isinstance(x, list):
    149                 ainvs = x
    150                 field = ainvs[0].parent()
    151         else:
    152             if isinstance(y, str):
    153                 field = x
    154                 X = sage.databases.cremona.CremonaDatabase()[y]
    155                 ainvs = list(X.a_invariants())
    156             else:
    157                 field = x
    158                 ainvs = y
    159         if not (isinstance(field, Ring) and isinstance(ainvs,list)):
    160             raise TypeError
    161        
    162         EllipticCurve_field.__init__(self, [field(x) for x in ainvs])
     178        EllipticCurve_field.__init__(self, K, ainvs)
    163179        self._point_class = ell_point.EllipticCurvePoint_number_field
    164180
    165181    def simon_two_descent(self, verbose=0, lim1=5, lim3=50, limtriv=10, maxprob=20, limbigprime=30):
  • sage/schemes/elliptic_curves/ell_padic_field.py

    diff --git a/sage/schemes/elliptic_curves/ell_padic_field.py b/sage/schemes/elliptic_curves/ell_padic_field.py
    a b  
    3232from sage.schemes.hyperelliptic_curves.hyperelliptic_padic_field import HyperellipticCurve_padic_field
    3333
    3434import sage.databases.cremona
    35 
     35from sage.structure.sequence import Sequence, Sequence_generic
    3636
    3737class EllipticCurve_padic_field(EllipticCurve_field, HyperellipticCurve_padic_field):
    3838    """
    3939    Elliptic curve over a padic field.
    4040    """
    41     def __init__(self, x, y=None):
     41    @staticmethod
     42    def __classcall__(cls, x, y=None):
    4243        """
    43         Constructor from [a1,a2,a3,a4,a6] or [a4,a6].
    44         EXAMPLES:
    45         sage: Qp=pAdicField(17)
    46         sage: E=EllipticCurve(Qp,[2,3]); E
    47         Elliptic Curve defined by y^2  = x^3 + (2+O(17^20))*x + (3+O(17^20)) over 17-adic Field with capped relative precision 20
    48         sage: E == loads(dumps(E))
    49         True
     44        Preprocess arguments such as to obtain a unique descriptor.
     45
     46        TESTS::
     47
     48            sage: Qp=pAdicField(17)
     49            sage: E=EllipticCurve(Qp,[2,3]); E
     50            Elliptic Curve defined by y^2 = x^3 + (2+O(17^20))*x + (3+O(17^20)) over 17-adic Field with capped relative precision 20
     51            sage: E is EllipticCurve(E.base_ring(), E.a_invariants())  # indirect doctest
     52            True
     53
    5054        """
    5155        if y is None:
    52             if isinstance(x, list):
     56            if isinstance(x, Sequence_generic) and x.is_immutable():
    5357                ainvs = x
    54                 field = ainvs[0].parent()
     58                field = ainvs.universe()
     59            elif isinstance(x, (list,tuple)):  # that covers sequences as well
     60                field = x[0].parent()
     61                ainvs = Sequence(x, universe=field, immutable=True)
     62            else:
     63                raise TypeError, "Since the second argument is not provided, the first must be a list or tuple"
    5564        else:
    5665            if isinstance(y, str):
    5766                field = x
    5867                X = sage.databases.cremona.CremonaDatabase()[y]
    59                 ainvs = [field(a) for a in X.a_invariants()]
     68                ainvs = Sequence(X.a_invariants(), universe=field, immutable=True)
    6069            else:
    6170                field = x
    62                 ainvs = y
    63         if not (isinstance(field, ring.Ring) and isinstance(ainvs,list)):
    64             raise TypeError
     71                ainvs = Sequence(y, universe=field, immutable=True)
     72        if not (isinstance(field, ring.Ring)):
     73            raise TypeError, "Can not determine the ring for that elliptic curve"
     74        return super(EllipticCurve_padic_field,cls).__classcall__(cls, field, ainvs)
    6575       
    66         EllipticCurve_field.__init__(self, [field(x) for x in ainvs])
     76    def __init__(self, field, ainvs):
     77        """
     78        Constructor from [a1,a2,a3,a4,a6] or [a4,a6].
     79
     80        EXAMPLES::
     81
     82            sage: Qp=pAdicField(17)
     83            sage: E=EllipticCurve(Qp,[2,3]); E
     84            Elliptic Curve defined by y^2  = x^3 + (2+O(17^20))*x + (3+O(17^20)) over 17-adic Field with capped relative precision 20
     85            sage: E is loads(dumps(E))
     86            True
     87
     88        """
     89        EllipticCurve_field.__init__(self, field, ainvs)
    6790
    6891        self._point_class = ell_point.EllipticCurvePoint_field
    6992        self._genus = 1
  • sage/schemes/elliptic_curves/ell_rational_field.py

    diff --git a/sage/schemes/elliptic_curves/ell_rational_field.py b/sage/schemes/elliptic_curves/ell_rational_field.py
    a b  
    9999from sage.misc.cachefunc import cached_method
    100100from copy import copy
    101101
     102from sage.structure.sequence import Sequence, Sequence_generic
     103
    102104factor = arith.factor
    103105mul = misc.mul
    104106next_prime = arith.next_prime
     
    154156        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
    155157
    156158    """
    157     def __init__(self, ainvs, extra=None):
    158         r"""
    159         Constructor for the EllipticCurve_rational_field class.
    160 
    161         INPUT:
    162 
    163         - ``ainvs`` (list or string) -- either `[a_1,a_2,a_3,a_4,a_6]`
    164           or `[a_4,a_6]` (with `a_1=a_2=a_3=0`) or a valid label from
    165           the database.
    166 
    167         .. note::
    168 
    169            See constructor.py for more variants.
    170        
    171         EXAMPLES::
    172        
    173             sage: E = EllipticCurve([1,2,3,4,5]); E
    174             Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
    175        
    176         Constructor from `[a_4,a_6]` sets `a_1=a_2=a_3=0`::
    177        
    178             sage: EllipticCurve([4,5]).ainvs()
    179             (0, 0, 0, 4, 5)
    180        
    181         Constructor from a label::
    182 
    183           sage: EllipticCurve('389a1')
    184           Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
    185 
     159    @staticmethod
     160    def __classcall__(cls, ainvs, extra=None):
     161        """
     162        Preprocess arguments such as to obtain a unique descriptor.
     163
     164        TESTS::
     165
     166            sage: E = EllipticCurve(j = 2019487744/1012581)
     167            sage: E
     168            Elliptic Curve defined by y^2 + y = x^3 + x^2 - 26*x - 28 over Rational Field
     169            sage: E.label()
     170            '1389a1'
     171            sage: E is EllipticCurve(E.label())  # indirect doctest
     172            True
     173            sage: E is EllipticCurve(E.base_ring(), E.a_invariants()) # indirect doctest
     174            True
    186175
    187176        """
    188177        if extra != None:   # possibility of two arguments (the first would be the field)
    189             ainvs = extra
     178            field = ainvs
     179            if field != Q:
     180                raise ValueError, "The given field must be the rational field"
     181            if isinstance(extra,Sequence_generic) and extra.is_immutable():
     182                AINVS = extra
     183            else:
     184                AINVS = Sequence(extra, universe=field, immutable=True)
     185            return super(EllipticCurve_rational_field, cls).__classcall__(cls, AINVS)
    190186        if isinstance(ainvs, str):
    191             label = ainvs
    192             X = sage.databases.cremona.CremonaDatabase()[label]
    193             EllipticCurve_number_field.__init__(self, Q, list(X.a_invariants()))
     187            #label = ainvs
     188            X = sage.databases.cremona.CremonaDatabase()[ainvs]
     189            AINVS = Sequence(X.a_invariants(), universe=Q, immutable=True)
     190            out = super(EllipticCurve_rational_field, cls).__classcall__(cls, Q, AINVS)
    194191            for attr in ['rank', 'torsion_order', 'cremona_label', 'conductor',
    195192                         'modular_degree', 'gens', 'regulator']:
    196193                s = "_EllipticCurve_rational_field__"+attr
    197194                if hasattr(X,s):
    198                     setattr(self, s, getattr(X, s))
    199             return
    200         EllipticCurve_number_field.__init__(self, Q, ainvs)
     195                    if hasattr(out,s):
     196                        attr = getattr(out,s)
     197                        if attr and getattr(X, s) != getattr(out,s):
     198                            return X  # breaking the unique parent condition
     199                    else:
     200                        setattr(out, s, getattr(X, s))
     201            return out
     202        if isinstance(ainvs, Sequence_generic) and ainvs.is_immutable():
     203            AINVS = ainvs
     204        else:
     205            field = Q
     206            AINVS = Sequence(ainvs, universe=Q, immutable=True)
     207        return super(EllipticCurve_rational_field, cls).__classcall__(cls, Q, AINVS)
     208
     209    def __init__(self, field, ainvs):
     210        r"""
     211        Constructor for the EllipticCurve_rational_field class.
     212
     213        INPUT:
     214
     215        - ``ainvs`` (list or string) -- `[a_1,a_2,a_3,a_4,a_6]`
     216
     217        .. note::
     218
     219           See constructor.py for more variants. There is a __classcall__
     220           method that will, in particular, take getting an elliptic curve
     221           out of the database, given its label.
     222
     223       
     224        EXAMPLES::
     225       
     226            sage: E = EllipticCurve([1,2,3,4,5]); E
     227            Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
     228       
     229        Constructor from `[a_4,a_6]` sets `a_1=a_2=a_3=0`::
     230       
     231            sage: EllipticCurve([4,5]).ainvs()
     232            (0, 0, 0, 4, 5)
     233       
     234        Constructor from a label::
     235
     236          sage: EllipticCurve('389a1')
     237          Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
     238
     239
     240        """
     241        if field != Q:
     242            raise ValueError, "The given field must be the rational field"
     243        EllipticCurve_number_field.__init__(self, field, ainvs)
    201244        self.__np = {}
    202245        self.__gens = {}
    203246        self.__rank = {}
     
    331374        """
    332375        Internal function to set the cached generators of this elliptic
    333376        curve to gens.
    334        
     377
    335378        .. warning::
    336379
    337380           No checking is done!
     
    344387            sage: E.gens() # random
    345388            [(-2 : 3 : 1), (-7/4 : 25/8 : 1), (1 : -1 : 1)]
    346389            sage: E._set_gens([]) # bogus list
     390            sage: E.gens()
     391            []
    347392            sage: E.rank()        # unchanged
    348393            3
    349             sage: E._set_gens([E(-2,3), E(-1,3), E(0,2)])
    350             sage: E.gens()
    351             [(-2 : 3 : 1), (-1 : 3 : 1), (0 : 2 : 1)]
    352394        """
    353395        self.__gens = {}
    354396        self.__gens[True] = [self.point(x, check=True) for x in gens]