def __init__(self, poly, ambient=None): """ Return the affine hypersurface in the space ambient defined by the polynomial poly. If ambient is not given, it will be constructed based on poly. EXAMPLES:: sage: A.<x, y, z> = AffineSpace(ZZ, 3) sage: AffineHypersurface(x*y-z^3, A) Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Integer Ring :: sage: A.<x, y, z> = QQ[] sage: AffineHypersurface(x*y-z^3) Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Rational Field TESTS:: sage: H = AffineHypersurface(x*y-z^3) sage: H == loads(dumps(H)) True """ if not is_MPolynomial(poly): raise TypeError, "Defining polynomial (= %s) must be a multivariate polynomial" % poly if ambient == None: R = poly.parent() from sage.schemes.affine.affine_space import AffineSpace ambient = AffineSpace(R.base_ring(), R.ngens()) ambient._coordinate_ring = R AlgebraicScheme_subscheme_affine.__init__(self, ambient, [poly])
def __init__(self, poly, ambient=None): """ Return the affine hypersurface in the space ambient defined by the polynomial poly. If ambient is not given, it will be constructed based on poly. EXAMPLES:: sage: A.<x, y, z> = AffineSpace(ZZ, 3) sage: AffineHypersurface(x*y-z^3, A) Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Integer Ring :: sage: A.<x, y, z> = QQ[] sage: AffineHypersurface(x*y-z^3) Affine hypersurface defined by -z^3 + x*y in Affine Space of dimension 3 over Rational Field TESTS:: sage: H = AffineHypersurface(x*y-z^3) sage: H == loads(dumps(H)) True """ if not is_MPolynomial(poly): raise TypeError("Defining polynomial (= %s) must be a multivariate polynomial"%poly) if ambient is None: R = poly.parent() from sage.schemes.affine.affine_space import AffineSpace ambient = AffineSpace(R.base_ring(), R.ngens()) ambient._coordinate_ring = R AlgebraicScheme_subscheme_affine.__init__(self, ambient, [poly])
def QuarticCurve(F, PP=None, check=False): """ Returns the quartic curve defined by the polynomial F. INPUT: - F -- a polynomial in three variables, homogeneous of degree 4 - PP -- a projective plane (default:None) - check -- whether to check for smoothness or not (default:False) EXAMPLES:: sage: x,y,z=PolynomialRing(QQ,['x','y','z']).gens() sage: QuarticCurve(x**4+y**4+z**4) Quartic Curve over Rational Field defined by x^4 + y^4 + z^4 TESTS:: sage: QuarticCurve(x**3+y**3) Traceback (most recent call last): ... ValueError: Argument F (=x^3 + y^3) must be a homogeneous polynomial of degree 4 sage: QuarticCurve(x**4+y**4+z**3) Traceback (most recent call last): ... ValueError: Argument F (=x^4 + y^4 + z^3) must be a homogeneous polynomial of degree 4 sage: x,y=PolynomialRing(QQ,['x','y']).gens() sage: QuarticCurve(x**4+y**4) Traceback (most recent call last): ... ValueError: Argument F (=x^4 + y^4) must be a polynomial in 3 variables """ if not is_MPolynomial(F): raise ValueError("Argument F (=%s) must be a multivariate polynomial" % F) P = F.parent() if not P.ngens() == 3: raise ValueError( "Argument F (=%s) must be a polynomial in 3 variables" % F) if not (F.is_homogeneous() and F.degree() == 4): raise ValueError( "Argument F (=%s) must be a homogeneous polynomial of degree 4" % F) if PP is not None: if not is_ProjectiveSpace(PP) and PP.dimension == 2: raise ValueError(f"Argument PP (={PP}) must be a projective plane") else: PP = ProjectiveSpace(P) if check: raise NotImplementedError( "Argument checking (for nonsingularity) is not implemented.") return QuarticCurve_generic(PP, F)
def Jacobian(X, **kwds): """ Return the Jacobian. INPUT: - ``X`` -- polynomial, algebraic variety, or anything else that has a Jacobian elliptic curve. - ``kwds`` -- optional keyword arguments. The input ``X`` can be one of the following: * A polynomial, see :func:`Jacobian_of_equation` for details. * A curve, see :func:`Jacobian_of_curve` for details. EXAMPLES:: sage: R.<u,v,w> = QQ[] sage: Jacobian(u^3+v^3+w^3) Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field sage: C = Curve(u^3+v^3+w^3) sage: Jacobian(C) Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field sage: P2.<u,v,w> = ProjectiveSpace(2, QQ) sage: C = P2.subscheme(u^3+v^3+w^3) sage: Jacobian(C) Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field sage: Jacobian(C, morphism=True) Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: u^3 + v^3 + w^3 To: Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field Defn: Defined on coordinates by sending (u : v : w) to (u*v^7*w + u*v^4*w^4 + u*v*w^7 : v^9 + 3/2*v^6*w^3 - 3/2*v^3*w^6 - w^9 : -v^6*w^3 - v^3*w^6) """ try: return X.jacobian(**kwds) except AttributeError: pass morphism = kwds.pop('morphism', False) from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if is_MPolynomial(X): if morphism: from sage.schemes.plane_curves.constructor import Curve return Jacobian_of_equation(X, curve=Curve(X), **kwds) else: return Jacobian_of_equation(X, **kwds) from sage.schemes.all import is_Scheme if is_Scheme(X) and X.dimension() == 1: return Jacobian_of_curve(X, morphism=morphism, **kwds)
def Jacobian(X, **kwds): """ Return the Jacobian. INPUT: - ``X`` -- polynomial, algebraic variety, or anything else that has a Jacobian elliptic curve. - ``kwds`` -- optional keyword arguments. The input ``X`` can be one of the following: * A polynomial, see :func:`Jacobian_of_equation` for details. * A curve, see :func:`Jacobian_of_curve` for details. EXAMPLES:: sage: R.<u,v,w> = QQ[] sage: Jacobian(u^3+v^3+w^3) Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field sage: C = Curve(u^3+v^3+w^3) sage: Jacobian(C) Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field sage: P2.<u,v,w> = ProjectiveSpace(2, QQ) sage: C = P2.subscheme(u^3+v^3+w^3) sage: Jacobian(C) Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field sage: Jacobian(C, morphism=True) Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: u^3 + v^3 + w^3 To: Elliptic Curve defined by y^2 = x^3 - 27/4 over Rational Field Defn: Defined on coordinates by sending (u : v : w) to (-u^4*v^4*w - u^4*v*w^4 - u*v^4*w^4 : 1/2*u^6*v^3 - 1/2*u^3*v^6 - 1/2*u^6*w^3 + 1/2*v^6*w^3 + 1/2*u^3*w^6 - 1/2*v^3*w^6 : u^3*v^3*w^3) """ try: return X.jacobian(**kwds) except AttributeError: pass morphism = kwds.pop('morphism', False) from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if is_MPolynomial(X): if morphism: from sage.schemes.curves.constructor import Curve return Jacobian_of_equation(X, curve=Curve(X), **kwds) else: return Jacobian_of_equation(X, **kwds) from sage.schemes.generic.scheme import is_Scheme if is_Scheme(X) and X.dimension() == 1: return Jacobian_of_curve(X, morphism=morphism, **kwds)
def __init__(self, a, b=None, c=None): r""" Create a binary quadratic form `ax^2 + bxy + cy^2`. INPUT: One of the following: - ``a`` -- either a 3-tuple of integers, or a quadratic homogeneous polynomial in two variables with integer coefficients - ``a``, ``b``, ``c`` -- three integers EXAMPLES:: sage: Q = BinaryQF([1,2,3]); Q x^2 + 2*x*y + 3*y^2 sage: Q = BinaryQF([1,2]) Traceback (most recent call last): ... TypeError: binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial or its coefficients sage: R.<x, y> = ZZ[] sage: f = x^2 + 2*x*y + 3*y^2 sage: BinaryQF(f) x^2 + 2*x*y + 3*y^2 sage: BinaryQF(f + x) Traceback (most recent call last): ... TypeError: binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial or its coefficients TESTS:: sage: BinaryQF(0) 0 """ from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if b is None and c is None: if (isinstance(a, (list, tuple)) and len(a) == 3): a, b, c = a elif a == 0: a = b = c = 0 elif (is_MPolynomial(a) and a.is_homogeneous() and a.base_ring() == ZZ and a.degree() == 2 and a.parent().ngens() == 2): x, y = a.parent().gens() a, b, c = [a.monomial_coefficient(mon) for mon in [x**2, x*y, y**2]] elif isinstance(a, pari_gen) and a.type() in ('t_QFI', 't_QFR'): # a has 3 or 4 components a, b, c = a[0], a[1], a[2] try: self._a = ZZ(a) self._b = ZZ(b) self._c = ZZ(c) except TypeError: raise TypeError('binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial or its coefficients') self._poly = None
def __init__(self, abc): r""" Creates the binary quadratic form `ax^2 + bxy + cy^2` from the triple [a,b,c] over `\ZZ` or from a polynomial. INPUT: - ``abc`` -- 3-tuple of integers, or a quadratic homogeneous polynomial in two variables with integer coefficients EXAMPLES:: sage: Q = BinaryQF([1,2,3]); Q x^2 + 2*x*y + 3*y^2 sage: Q = BinaryQF([1,2]) Traceback (most recent call last): ... TypeError: Binary quadratic form must be given by a list of three coefficients sage: R.<x, y> = ZZ[] sage: f = x^2 + 2*x*y + 3*y^2 sage: BinaryQF(f) x^2 + 2*x*y + 3*y^2 sage: BinaryQF(f + x) Traceback (most recent call last): ... TypeError: Binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial TESTS:: sage: BinaryQF(0) 0 """ if isinstance(abc, (list, tuple)): if len(abc) != 3: # Check we have three coefficients raise TypeError( "Binary quadratic form must be given by a list of three coefficients" ) self._a, self._b, self._c = [ZZ(x) for x in abc] else: f = abc from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if f.is_zero(): self._a, self._b, self._c = [ZZ(0), ZZ(0), ZZ(0)] elif (is_MPolynomial(f) and f.is_homogeneous() and f.base_ring() == ZZ and f.degree() == 2 and f.parent().ngens() == 2): x, y = f.parent().gens() self._a, self._b, self._c = [ f.monomial_coefficient(mon) for mon in [x**2, x * y, y**2] ] else: raise TypeError( "Binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial" )
def QuarticCurve(F, PP=None, check=False): """ Returns the quartic curve defined by the polynomial F. INPUT: - F -- a polynomial in three variables, homogeneous of degree 4 - PP -- a projective plane (default:None) - check -- whether to check for smoothness or not (default:False) EXAMPLES:: sage: x,y,z=PolynomialRing(QQ,['x','y','z']).gens() sage: QuarticCurve(x**4+y**4+z**4) Quartic Curve over Rational Field defined by x^4 + y^4 + z^4 TESTS:: sage: QuarticCurve(x**3+y**3) Traceback (most recent call last): ... ValueError: Argument F (=x^3 + y^3) must be a homogeneous polynomial of degree 4 sage: QuarticCurve(x**4+y**4+z**3) Traceback (most recent call last): ... ValueError: Argument F (=x^4 + y^4 + z^3) must be a homogeneous polynomial of degree 4 sage: x,y=PolynomialRing(QQ,['x','y']).gens() sage: QuarticCurve(x**4+y**4) Traceback (most recent call last): ... ValueError: Argument F (=x^4 + y^4) must be a polynomial in 3 variables """ if not is_MPolynomial(F): raise ValueError("Argument F (=%s) must be a multivariate polynomial"%F) P = F.parent() if not P.ngens() == 3: raise ValueError("Argument F (=%s) must be a polynomial in 3 variables"%F) if not(F.is_homogeneous() and F.degree()==4): raise ValueError("Argument F (=%s) must be a homogeneous polynomial of degree 4"%F) if not PP is None: if not is_ProjectiveSpace(PP) and PP.dimension == 2: raise ValueError("Argument PP (=%s) must be a projective plane"%PP) else: PP = ProjectiveSpace(P) if check: raise NotImplementedError("Argument checking (for nonsingularity) is not implemented.") return QuarticCurve_generic(PP, F)
def __init__(self, abc): r""" Creates the binary quadratic form `ax^2 + bxy + cy^2` from the triple [a,b,c] over `\ZZ` or from a polynomial. INPUT: - ``abc`` -- 3-tuple of integers, or a quadratic homogeneous polynomial in two variables with integer coefficients EXAMPLES:: sage: Q = BinaryQF([1,2,3]); Q x^2 + 2*x*y + 3*y^2 sage: Q = BinaryQF([1,2]) Traceback (most recent call last): ... TypeError: Binary quadratic form must be given by a list of three coefficients sage: R.<x, y> = ZZ[] sage: f = x^2 + 2*x*y + 3*y^2 sage: BinaryQF(f) x^2 + 2*x*y + 3*y^2 sage: BinaryQF(f + x) Traceback (most recent call last): ... TypeError: Binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial TESTS:: sage: BinaryQF(0) 0 """ if isinstance(abc, (list, tuple)): if len(abc) != 3: # Check we have three coefficients raise TypeError, "Binary quadratic form must be given by a list of three coefficients" self._a, self._b, self._c = [ZZ(x) for x in abc] else: f = abc from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if f.is_zero(): self._a, self._b, self._c = [ZZ(0), ZZ(0), ZZ(0)] elif (is_MPolynomial(f) and f.is_homogeneous() and f.base_ring() == ZZ and f.degree() == 2 and f.parent().ngens() == 2): x, y = f.parent().gens() self._a, self._b, self._c = [f.monomial_coefficient(mon) for mon in [x**2, x*y, y**2]] else: raise TypeError, "Binary quadratic form must be given by a quadratic homogeneous bivariate integer polynomial"
def __init__(self, poly, ambient=None): """ Return the projective hypersurface in the space ambient defined by the polynomial poly. If ambient is not given, it will be constructed based on poly. EXAMPLES:: sage: P.<x, y, z> = ProjectiveSpace(ZZ, 2) sage: ProjectiveHypersurface(x-y, P) Projective hypersurface defined by x - y in Projective Space of dimension 2 over Integer Ring :: sage: R.<x, y, z> = QQ[] sage: ProjectiveHypersurface(x-y) Projective hypersurface defined by x - y in Projective Space of dimension 2 over Rational Field TESTS:: sage: H = ProjectiveHypersurface(x-y) sage: H == loads(dumps(H)) True """ if not is_MPolynomial(poly): raise TypeError( "Defining polynomial (=%s) must be a multivariate polynomial." % poly) if not poly.is_homogeneous(): raise TypeError("Defining polynomial (=%s) must be homogeneous." % poly) if ambient is None: R = poly.parent() from sage.schemes.projective.projective_space import ProjectiveSpace ambient = ProjectiveSpace(R.base_ring(), R.ngens() - 1) ambient._coordinate_ring = R AlgebraicScheme_subscheme_projective.__init__(self, ambient, [poly])
def __init__(self, poly, ambient=None): """ Return the projective hypersurface in the space ambient defined by the polynomial poly. If ambient is not given, it will be constructed based on poly. EXAMPLES:: sage: P.<x, y, z> = ProjectiveSpace(ZZ, 2) sage: ProjectiveHypersurface(x-y, P) Projective hypersurface defined by x - y in Projective Space of dimension 2 over Integer Ring :: sage: R.<x, y, z> = QQ[] sage: ProjectiveHypersurface(x-y) Projective hypersurface defined by x - y in Projective Space of dimension 2 over Rational Field TESTS:: sage: H = ProjectiveHypersurface(x-y) sage: H == loads(dumps(H)) True """ if not is_MPolynomial(poly): raise TypeError, \ "Defining polynomial (=%s) must be a multivariate polynomial."%poly if not poly.is_homogeneous(): raise TypeError, "Defining polynomial (=%s) must be homogeneous."%poly if ambient == None: R = poly.parent() from sage.schemes.projective.projective_space import ProjectiveSpace ambient = ProjectiveSpace(R.base_ring(), R.ngens()-1) ambient._coordinate_ring = R AlgebraicScheme_subscheme_projective.__init__(self, ambient, [poly])
def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True, **kwds): """ Return a ``UniqueFactory`` key and possibly extra parameters. INPUT: See the documentation for :class:`EllipticCurveFactory`. OUTPUT: A pair ``(key, extra_args)``: - ``key`` has the form `(R, (a_1, a_2, a_3, a_4, a_6))`, representing a ring and the Weierstrass coefficients of an elliptic curve over that ring; - ``extra_args`` is a dictionary containing additional data to be inserted into the elliptic curve structure. EXAMPLES:: sage: EllipticCurve.create_key_and_extra_args(j=8000) ((Rational Field, (0, -1, 0, -3, -1)), {}) When constructing a curve over `\\QQ` from a Cremona or LMFDB label, the invariants from the database are returned as ``extra_args``:: sage: key, data = EllipticCurve.create_key_and_extra_args('389.a1') sage: key (Rational Field, (0, 1, 1, -2, 0)) sage: data['conductor'] 389 sage: data['cremona_label'] '389a1' sage: data['lmfdb_label'] '389.a1' sage: data['rank'] 2 sage: data['torsion_order'] 1 User-specified keywords are also included in ``extra_args``:: sage: key, data = EllipticCurve.create_key_and_extra_args((0, 0, 1, -23737, 960366), rank=4) sage: data['rank'] 4 Furthermore, keywords takes precedence over data from the database, which can be used to specify an alternative set of generators for the Mordell-Weil group:: sage: key, data = EllipticCurve.create_key_and_extra_args('5077a1', gens=[[1, -1], [-2, 3], [4, -7]]) sage: data['gens'] [[1, -1], [-2, 3], [4, -7]] sage: E = EllipticCurve.create_object(0, key, **data) sage: E.gens() [(-2 : 3 : 1), (1 : -1 : 1), (4 : -7 : 1)] Note that elliptic curves are equal if and only they have the same base ring and Weierstrass equation; the data in ``extra_args`` do not influence comparison of elliptic curves. A consequence of this is that passing keyword arguments only works when constructing an elliptic curve the first time: sage: E = EllipticCurve('433a1', gens=[[-1, 1], [3, 4]]) sage: E.gens() [(-1 : 1 : 1), (3 : 4 : 1)] sage: E = EllipticCurve('433a1', gens=[[-1, 0], [0, 1]]) sage: E.gens() [(-1 : 1 : 1), (3 : 4 : 1)] .. WARNING:: Manually specifying extra data is almost never necessary and is not guaranteed to have any effect, as the above example shows. Almost no checking is done, so specifying incorrect data may lead to wrong results of computations instead of errors or warnings. """ R = None if is_Ring(x): (R, x) = (x, y) if j is not None: if R is not None: try: j = R(j) except (ZeroDivisionError, ValueError, TypeError): raise ValueError("First parameter must be a ring containing %s" % j) elif x is not None: raise ValueError("First parameter (if present) must be a ring when j is specified") x = coefficients_from_j(j, minimal_twist) if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if is_MPolynomial(x): if y is None: x = coefficients_from_Weierstrass_polynomial(x) else: x = coefficients_from_cubic(x, y, morphism=False) if isinstance(x, basestring): # Interpret x as a Cremona or LMFDB label. from sage.databases.cremona import CremonaDatabase x, data = CremonaDatabase().coefficients_and_data(x) # User-provided keywords may override database entries. data.update(kwds) kwds = data if not isinstance(x, (list, tuple)): raise TypeError("invalid input to EllipticCurve constructor") if len(x) == 2: x = (0, 0, 0, x[0], x[1]) elif len(x) != 5: raise ValueError("sequence of coefficients must have length 2 or 5") if R is None: R = Sequence(x).universe() if R in (rings.ZZ, int, long): R = rings.QQ return (R, tuple(R(a) for a in x)), kwds
def Conic(base_field, F=None, names=None, unique=True): r""" Return the plane projective conic curve defined by ``F`` over ``base_field``. The input form ``Conic(F, names=None)`` is also accepted, in which case the fraction field of the base ring of ``F`` is used as base field. INPUT: - ``base_field`` -- The base field of the conic. - ``names`` -- a list, tuple, or comma separated string of three variable names specifying the names of the coordinate functions of the ambient space `\Bold{P}^3`. If not specified or read off from ``F``, then this defaults to ``'x,y,z'``. - ``F`` -- a polynomial, list, matrix, ternary quadratic form, or list or tuple of 5 points in the plane. If ``F`` is a polynomial or quadratic form, then the output is the curve in the projective plane defined by ``F = 0``. If ``F`` is a polynomial, then it must be a polynomial of degree at most 2 in 2 variables, or a homogeneous polynomial in of degree 2 in 3 variables. If ``F`` is a matrix, then the output is the zero locus of `(x,y,z) F (x,y,z)^t`. If ``F`` is a list of coefficients, then it has length 3 or 6 and gives the coefficients of the monomials `x^2, y^2, z^2` or all 6 monomials `x^2, xy, xz, y^2, yz, z^2` in lexicographic order. If ``F`` is a list of 5 points in the plane, then the output is a conic through those points. - ``unique`` -- Used only if ``F`` is a list of points in the plane. If the conic through the points is not unique, then raise ``ValueError`` if and only if ``unique`` is True OUTPUT: A plane projective conic curve defined by ``F`` over a field. EXAMPLES: Conic curves given by polynomials :: sage: X,Y,Z = QQ['X,Y,Z'].gens() sage: Conic(X^2 - X*Y + Y^2 - Z^2) Projective Conic Curve over Rational Field defined by X^2 - X*Y + Y^2 - Z^2 sage: x,y = GF(7)['x,y'].gens() sage: Conic(x^2 - x + 2*y^2 - 3, 'U,V,W') Projective Conic Curve over Finite Field of size 7 defined by U^2 + 2*V^2 - U*W - 3*W^2 Conic curves given by matrices :: sage: Conic(matrix(QQ, [[1, 2, 0], [4, 0, 0], [7, 0, 9]]), 'x,y,z') Projective Conic Curve over Rational Field defined by x^2 + 6*x*y + 7*x*z + 9*z^2 sage: x,y,z = GF(11)['x,y,z'].gens() sage: C = Conic(x^2+y^2-2*z^2); C Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2 sage: Conic(C.symmetric_matrix(), 'x,y,z') Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2 Conics given by coefficients :: sage: Conic(QQ, [1,2,3]) Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + 3*z^2 sage: Conic(GF(7), [1,2,3,4,5,6], 'X') Projective Conic Curve over Finite Field of size 7 defined by X0^2 + 2*X0*X1 - 3*X1^2 + 3*X0*X2 - 2*X1*X2 - X2^2 The conic through a set of points :: sage: C = Conic(QQ, [[10,2],[3,4],[-7,6],[7,8],[9,10]]); C Projective Conic Curve over Rational Field defined by x^2 + 13/4*x*y - 17/4*y^2 - 35/2*x*z + 91/4*y*z - 37/2*z^2 sage: C.rational_point() (10 : 2 : 1) sage: C.point([3,4]) (3 : 4 : 1) sage: a=AffineSpace(GF(13),2) sage: Conic([a([x,x^2]) for x in range(5)]) Projective Conic Curve over Finite Field of size 13 defined by x^2 - y*z """ if not (base_field is None or isinstance(base_field, IntegralDomain)): if names is None: names = F F = base_field base_field = None if isinstance(F, (list,tuple)): if len(F) == 1: return Conic(base_field, F[0], names) if names is None: names = 'x,y,z' if len(F) == 5: L=[] for f in F: if isinstance(f, SchemeMorphism_point_affine): C = Sequence(f, universe = base_field) if len(C) != 2: raise TypeError("points in F (=%s) must be planar"%F) C.append(1) elif isinstance(f, SchemeMorphism_point_projective_field): C = Sequence(f, universe = base_field) elif isinstance(f, (list, tuple)): C = Sequence(f, universe = base_field) if len(C) == 2: C.append(1) else: raise TypeError("F (=%s) must be a sequence of planar " \ "points" % F) if len(C) != 3: raise TypeError("points in F (=%s) must be planar" % F) P = C.universe() if not isinstance(P, IntegralDomain): raise TypeError("coordinates of points in F (=%s) must " \ "be in an integral domain" % F) L.append(Sequence([C[0]**2, C[0]*C[1], C[0]*C[2], C[1]**2, C[1]*C[2], C[2]**2], P.fraction_field())) M=Matrix(L) if unique and M.rank() != 5: raise ValueError("points in F (=%s) do not define a unique " \ "conic" % F) con = Conic(base_field, Sequence(M.right_kernel().gen()), names) con.point(F[0]) return con F = Sequence(F, universe = base_field) base_field = F.universe().fraction_field() temp_ring = PolynomialRing(base_field, 3, names) (x,y,z) = temp_ring.gens() if len(F) == 3: return Conic(F[0]*x**2 + F[1]*y**2 + F[2]*z**2) if len(F) == 6: return Conic(F[0]*x**2 + F[1]*x*y + F[2]*x*z + F[3]*y**2 + \ F[4]*y*z + F[5]*z**2) raise TypeError("F (=%s) must be a sequence of 3 or 6" \ "coefficients" % F) if is_QuadraticForm(F): F = F.matrix() if is_Matrix(F) and F.is_square() and F.ncols() == 3: if names is None: names = 'x,y,z' temp_ring = PolynomialRing(F.base_ring(), 3, names) F = vector(temp_ring.gens()) * F * vector(temp_ring.gens()) if not is_MPolynomial(F): raise TypeError("F (=%s) must be a three-variable polynomial or " \ "a sequence of points or coefficients" % F) if F.total_degree() != 2: raise TypeError("F (=%s) must have degree 2" % F) if base_field is None: base_field = F.base_ring() if not isinstance(base_field, IntegralDomain): raise ValueError("Base field (=%s) must be a field" % base_field) base_field = base_field.fraction_field() if names is None: names = F.parent().variable_names() pol_ring = PolynomialRing(base_field, 3, names) if F.parent().ngens() == 2: (x,y,z) = pol_ring.gens() F = pol_ring(F(x/z,y/z)*z**2) if F == 0: raise ValueError("F must be nonzero over base field %s" % base_field) if F.total_degree() != 2: raise TypeError("F (=%s) must have degree 2 over base field %s" % \ (F, base_field)) if F.parent().ngens() == 3: P2 = ProjectiveSpace(2, base_field, names) if is_PrimeFiniteField(base_field): return ProjectiveConic_prime_finite_field(P2, F) if is_FiniteField(base_field): return ProjectiveConic_finite_field(P2, F) if is_RationalField(base_field): return ProjectiveConic_rational_field(P2, F) if is_NumberField(base_field): return ProjectiveConic_number_field(P2, F) if is_FractionField(base_field) and (is_PolynomialRing(base_field.ring()) or is_MPolynomialRing(base_field.ring())): return ProjectiveConic_rational_function_field(P2, F) return ProjectiveConic_field(P2, F) raise TypeError("Number of variables of F (=%s) must be 2 or 3" % F)
def Curve(F, A=None): """ Return the plane or space curve defined by ``F``, where ``F`` can be either a multivariate polynomial, a list or tuple of polynomials, or an algebraic scheme. If no ambient space is passed in for ``A``, and if ``F`` is not an algebraic scheme, a new ambient space is constructed. Also not specifying an ambient space will cause the curve to be defined in either affine or projective space based on properties of ``F``. In particular, if ``F`` contains a nonhomogenous polynomial, the curve is affine, and if ``F`` consists of homogenous polynomials, then the curve is projective. INPUT: - ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme. - ``A`` -- (default: None) an ambient space in which to create the curve. EXAMPLE: A projective plane curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3); C Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3 sage: C.genus() 1 EXAMPLE: Affine plane curves :: sage: x,y = GF(7)['x,y'].gens() sage: C = Curve(y^2 + x^3 + x^10); C Affine Plane Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2 sage: C.genus() 0 sage: x, y = QQ['x,y'].gens() sage: Curve(x^3 + y^3 + 1) Affine Plane Curve over Rational Field defined by x^3 + y^3 + 1 EXAMPLE: A projective space curve :: sage: x,y,z,w = QQ['x,y,z,w'].gens() sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C Projective Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4 sage: C.genus() 13 EXAMPLE: An affine space curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve([y^2 + x^3 + x^10 + z^7, x^2 + y^2]); C Affine Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2 sage: C.genus() 47 EXAMPLE: We can also make non-reduced non-irreducible curves. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve((x-y)*(x+y)) Projective Conic Curve over Rational Field defined by x^2 - y^2 sage: Curve((x-y)^2*(x+y)^2) Projective Plane Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4 EXAMPLE: A union of curves is a curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3) sage: D = Curve(x^4 + y^4 + z^4) sage: C.union(D) Projective Plane Curve over Rational Field defined by x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7 The intersection is not a curve, though it is a scheme. :: sage: X = C.intersection(D); X Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^3 + y^3 + z^3, x^4 + y^4 + z^4 Note that the intersection has dimension `0`. :: sage: X.dimension() 0 sage: I = X.defining_ideal(); I Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field EXAMPLE: In three variables, the defining equation must be homogeneous. If the parent polynomial ring is in three variables, then the defining ideal must be homogeneous. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve(x^2+y^2) Projective Conic Curve over Rational Field defined by x^2 + y^2 sage: Curve(x^2+y^2+z) Traceback (most recent call last): ... TypeError: x^2 + y^2 + z is not a homogeneous polynomial The defining polynomial must always be nonzero:: sage: P1.<x,y> = ProjectiveSpace(1,GF(5)) sage: Curve(0*x) Traceback (most recent call last): ... ValueError: defining polynomial of curve must be nonzero :: sage: A.<x,y,z> = AffineSpace(QQ, 3) sage: C = Curve([y - x^2, z - x^3], A) sage: A == C.ambient_space() True """ if not A is None: if not isinstance(F, (list, tuple)): return Curve([F], A) if not is_AmbientSpace(A): raise TypeError( "A (=%s) must be either an affine or projective space" % A) if not all([f.parent() == A.coordinate_ring() for f in F]): raise TypeError("F (=%s) must be a list or tuple of polynomials of the coordinate ring of " \ "A (=%s)"%(F, A)) n = A.dimension_relative() if n < 2: raise TypeError( "A (=%s) must be either an affine or projective space of dimension > 1" % A) # there is no dimension check when initializing a plane curve, so check here that F consists # of a single nonconstant polynomial if n == 2: if len(F) != 1 or F[0] == 0 or not is_MPolynomial(F[0]): raise TypeError( "F (=%s) must consist of a single nonconstant polynomial to define a plane curve" % (F, )) if is_AffineSpace(A): if n > 2: return AffineCurve(A, F) k = A.base_ring() if is_FiniteField(k): if k.is_prime_field(): return AffinePlaneCurve_prime_finite_field(A, F[0]) return AffinePlaneCurve_finite_field(A, F[0]) return AffinePlaneCurve(A, F[0]) elif is_ProjectiveSpace(A): if not all([f.is_homogeneous() for f in F]): raise TypeError( "polynomials defining a curve in a projective space must be homogeneous" ) if n > 2: return ProjectiveCurve(A, F) k = A.base_ring() if is_FiniteField(k): if k.is_prime_field(): return ProjectivePlaneCurve_prime_finite_field(A, F[0]) return ProjectivePlaneCurve_finite_field(A, F[0]) return ProjectivePlaneCurve(A, F[0]) if is_AlgebraicScheme(F): return Curve(F.defining_polynomials(), F.ambient_space()) if isinstance(F, (list, tuple)): if len(F) == 1: return Curve(F[0]) F = Sequence(F) P = F.universe() if not is_MPolynomialRing(P): raise TypeError( "universe of F must be a multivariate polynomial ring") for f in F: if not f.is_homogeneous(): A = AffineSpace(P.ngens(), P.base_ring()) A._coordinate_ring = P return AffineCurve(A, F) A = ProjectiveSpace(P.ngens() - 1, P.base_ring()) A._coordinate_ring = P return ProjectiveCurve(A, F) if not is_MPolynomial(F): raise TypeError("F (=%s) must be a multivariate polynomial" % F) P = F.parent() k = F.base_ring() if F.parent().ngens() == 2: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") A2 = AffineSpace(2, P.base_ring()) A2._coordinate_ring = P if is_FiniteField(k): if k.is_prime_field(): return AffinePlaneCurve_prime_finite_field(A2, F) else: return AffinePlaneCurve_finite_field(A2, F) else: return AffinePlaneCurve(A2, F) elif F.parent().ngens() == 3: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") P2 = ProjectiveSpace(2, P.base_ring()) P2._coordinate_ring = P if F.total_degree() == 2 and k.is_field(): return Conic(F) if is_FiniteField(k): if k.is_prime_field(): return ProjectivePlaneCurve_prime_finite_field(P2, F) else: return ProjectivePlaneCurve_finite_field(P2, F) else: return ProjectivePlaneCurve(P2, F) else: raise TypeError("Number of variables of F (=%s) must be 2 or 3" % F)
def Curve(F): """ Return the plane or space curve defined by `F`, where `F` can be either a multivariate polynomial, a list or tuple of polynomials, or an algebraic scheme. If `F` is in two variables the curve is affine, and if it is homogenous in `3` variables, then the curve is projective. EXAMPLE: A projective plane curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3); C Projective Curve over Rational Field defined by x^3 + y^3 + z^3 sage: C.genus() 1 EXAMPLE: Affine plane curves :: sage: x,y = GF(7)['x,y'].gens() sage: C = Curve(y^2 + x^3 + x^10); C Affine Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2 sage: C.genus() 0 sage: x, y = QQ['x,y'].gens() sage: Curve(x^3 + y^3 + 1) Affine Curve over Rational Field defined by x^3 + y^3 + 1 EXAMPLE: A projective space curve :: sage: x,y,z,w = QQ['x,y,z,w'].gens() sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C Projective Space Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4 sage: C.genus() 13 EXAMPLE: An affine space curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve([y^2 + x^3 + x^10 + z^7, x^2 + y^2]); C Affine Space Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2 sage: C.genus() 47 EXAMPLE: We can also make non-reduced non-irreducible curves. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve((x-y)*(x+y)) Projective Conic Curve over Rational Field defined by x^2 - y^2 sage: Curve((x-y)^2*(x+y)^2) Projective Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4 EXAMPLE: A union of curves is a curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3) sage: D = Curve(x^4 + y^4 + z^4) sage: C.union(D) Projective Curve over Rational Field defined by x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7 The intersection is not a curve, though it is a scheme. :: sage: X = C.intersection(D); X Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^3 + y^3 + z^3, x^4 + y^4 + z^4 Note that the intersection has dimension `0`. :: sage: X.dimension() 0 sage: I = X.defining_ideal(); I Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field EXAMPLE: In three variables, the defining equation must be homogeneous. If the parent polynomial ring is in three variables, then the defining ideal must be homogeneous. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve(x^2+y^2) Projective Conic Curve over Rational Field defined by x^2 + y^2 sage: Curve(x^2+y^2+z) Traceback (most recent call last): ... TypeError: x^2 + y^2 + z is not a homogeneous polynomial! The defining polynomial must always be nonzero:: sage: P1.<x,y> = ProjectiveSpace(1,GF(5)) sage: Curve(0*x) Traceback (most recent call last): ... ValueError: defining polynomial of curve must be nonzero """ if is_AlgebraicScheme(F): return Curve(F.defining_polynomials()) if isinstance(F, (list, tuple)): if len(F) == 1: return Curve(F[0]) F = Sequence(F) P = F.universe() if not is_MPolynomialRing(P): raise TypeError, "universe of F must be a multivariate polynomial ring" for f in F: if not f.is_homogeneous(): A = AffineSpace(P.ngens(), P.base_ring()) A._coordinate_ring = P return AffineSpaceCurve_generic(A, F) A = ProjectiveSpace(P.ngens() - 1, P.base_ring()) A._coordinate_ring = P return ProjectiveSpaceCurve_generic(A, F) if not is_MPolynomial(F): raise TypeError, "F (=%s) must be a multivariate polynomial" % F P = F.parent() k = F.base_ring() if F.parent().ngens() == 2: if F == 0: raise ValueError, "defining polynomial of curve must be nonzero" A2 = AffineSpace(2, P.base_ring()) A2._coordinate_ring = P if is_FiniteField(k): if k.is_prime_field(): return AffineCurve_prime_finite_field(A2, F) else: return AffineCurve_finite_field(A2, F) else: return AffineCurve_generic(A2, F) elif F.parent().ngens() == 3: if F == 0: raise ValueError, "defining polynomial of curve must be nonzero" P2 = ProjectiveSpace(2, P.base_ring()) P2._coordinate_ring = P if F.total_degree() == 2 and k.is_field(): return Conic(F) if is_FiniteField(k): if k.is_prime_field(): return ProjectiveCurve_prime_finite_field(P2, F) else: return ProjectiveCurve_finite_field(P2, F) else: return ProjectiveCurve_generic(P2, F) else: raise TypeError, "Number of variables of F (=%s) must be 2 or 3" % F
def __call__(self, x, n=0): r""" Coerces the element x into this Laurent series ring. INPUT: - ``x`` - the element to coerce - ``n`` - the result of the coercion will be multiplied by `t^n` (default: 0) EXAMPLES:: sage: R.<u> = LaurentSeriesRing(Qp(5, 10)) sage: S.<t> = LaurentSeriesRing(RationalField()) sage: print R(t + t^2 + O(t^3)) (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3) Note that coercing an element into its own parent just produces that element again (since Laurent series are immutable):: sage: u is R(u) True Rational functions are accepted:: sage: I = sqrt(-1) sage: K.<I> = QQ[I] sage: P.<t> = PolynomialRing(K) sage: L.<u> = LaurentSeriesRing(QQ[I]) sage: L((t*I)/(t^3+I*2*t)) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) :: sage: L(t*I) / L(t^3+I*2*t) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) Various conversions from PARI (see also #2508):: sage: L.<q> = LaurentSeriesRing(QQ) sage: L.set_default_prec(10) sage: L(pari('1/x')) q^-1 sage: L(pari('poltchebi(5)')) 5*q - 20*q^3 + 16*q^5 sage: L(pari('poltchebi(5) - 1/x^4')) -q^-4 + 5*q - 20*q^3 + 16*q^5 sage: L(pari('1/poltchebi(5)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9) sage: L(pari('poltchebi(5) + O(x^40)')) 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)')) -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('1/poltchebi(5) + O(x^10)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10) sage: L(pari('1/poltchebi(5) + O(x^10)'), -10) # Multiply by q^-10 1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1) sage: L(pari('O(x^-10)')) O(q^-10) """ from sage.rings.fraction_field_element import is_FractionFieldElement from sage.rings.polynomial.polynomial_element import is_Polynomial from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if isinstance(x, laurent_series_ring_element.LaurentSeries) and n==0 and self is x.parent(): return x # ok, since Laurent series are immutable (no need to make a copy) elif isinstance(x, pari_gen): t = x.type() if t == "t_RFRAC": # Rational function x = self(self.polynomial_ring()(x.numerator())) / \ self(self.polynomial_ring()(x.denominator())) return (x << n) elif t == "t_SER": # Laurent series n += x._valp() bigoh = n + x.length() x = self(self.polynomial_ring()(x.Vec())) return (x << n).add_bigoh(bigoh) else: # General case, pretend to be a polynomial return self(self.polynomial_ring()(x)) << n elif is_FractionFieldElement(x) and \ (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \ (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())): x = self(x.numerator())/self(x.denominator()) return (x << n) else: return laurent_series_ring_element.LaurentSeries(self, x, n)
def Curve(F, A=None): """ Return the plane or space curve defined by ``F``, where ``F`` can be either a multivariate polynomial, a list or tuple of polynomials, or an algebraic scheme. If no ambient space is passed in for ``A``, and if ``F`` is not an algebraic scheme, a new ambient space is constructed. Also not specifying an ambient space will cause the curve to be defined in either affine or projective space based on properties of ``F``. In particular, if ``F`` contains a nonhomogenous polynomial, the curve is affine, and if ``F`` consists of homogenous polynomials, then the curve is projective. INPUT: - ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme. - ``A`` -- (default: None) an ambient space in which to create the curve. EXAMPLES: A projective plane curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3); C Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3 sage: C.genus() 1 Affine plane curves. :: sage: x,y = GF(7)['x,y'].gens() sage: C = Curve(y^2 + x^3 + x^10); C Affine Plane Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2 sage: C.genus() 0 sage: x, y = QQ['x,y'].gens() sage: Curve(x^3 + y^3 + 1) Affine Plane Curve over Rational Field defined by x^3 + y^3 + 1 A projective space curve. :: sage: x,y,z,w = QQ['x,y,z,w'].gens() sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C Projective Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4 sage: C.genus() 13 An affine space curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve([y^2 + x^3 + x^10 + z^7, x^2 + y^2]); C Affine Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2 sage: C.genus() 47 We can also make non-reduced non-irreducible curves. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve((x-y)*(x+y)) Projective Conic Curve over Rational Field defined by x^2 - y^2 sage: Curve((x-y)^2*(x+y)^2) Projective Plane Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4 A union of curves is a curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3) sage: D = Curve(x^4 + y^4 + z^4) sage: C.union(D) Projective Plane Curve over Rational Field defined by x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7 The intersection is not a curve, though it is a scheme. :: sage: X = C.intersection(D); X Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^3 + y^3 + z^3, x^4 + y^4 + z^4 Note that the intersection has dimension 0. :: sage: X.dimension() 0 sage: I = X.defining_ideal(); I Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field If only a polynomial in three variables is given, then it must be homogeneous such that a projective curve is constructed. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve(x^2+y^2) Projective Conic Curve over Rational Field defined by x^2 + y^2 sage: Curve(x^2+y^2+z) Traceback (most recent call last): ... TypeError: x^2 + y^2 + z is not a homogeneous polynomial An ambient space can be specified to construct a space curve in an affine or a projective space. :: sage: A.<x,y,z> = AffineSpace(QQ, 3) sage: C = Curve([y - x^2, z - x^3], A) sage: C Affine Curve over Rational Field defined by -x^2 + y, -x^3 + z sage: A == C.ambient_space() True The defining polynomial must be nonzero unless the ambient space itself is of dimension 1. :: sage: P1.<x,y> = ProjectiveSpace(1,GF(5)) sage: S = P1.coordinate_ring() sage: Curve(S(0), P1) Projective Line over Finite Field of size 5 sage: Curve(P1) Projective Line over Finite Field of size 5 :: sage: A1.<x> = AffineSpace(1, QQ) sage: R = A1.coordinate_ring() sage: Curve(R(0), A1) Affine Line over Rational Field sage: Curve(A1) Affine Line over Rational Field """ if A is None: if is_AmbientSpace(F) and F.dimension() == 1: return Curve(F.coordinate_ring().zero(), F) if is_AlgebraicScheme(F): return Curve(F.defining_polynomials(), F.ambient_space()) if isinstance(F, (list, tuple)): P = Sequence(F).universe() if not is_MPolynomialRing(P): raise TypeError("universe of F must be a multivariate polynomial ring") for f in F: if not f.is_homogeneous(): A = AffineSpace(P.ngens(), P.base_ring(), names=P.variable_names()) A._coordinate_ring = P break else: A = ProjectiveSpace(P.ngens()-1, P.base_ring(), names=P.variable_names()) A._coordinate_ring = P elif is_MPolynomial(F): # define a plane curve P = F.parent() k = F.base_ring() if not k.is_field(): if k.is_integral_domain(): # upgrade to a field P = P.change_ring(k.fraction_field()) F = P(F) k = F.base_ring() else: raise TypeError("not a multivariate polynomial over a field or an integral domain") if F.parent().ngens() == 2: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") A = AffineSpace(2, P.base_ring(), names=P.variable_names()) A._coordinate_ring = P elif F.parent().ngens() == 3: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") # special case: construct a conic curve if F.total_degree() == 2 and k.is_field(): return Conic(k, F) A = ProjectiveSpace(2, P.base_ring(), names=P.variable_names()) A._coordinate_ring = P elif F.parent().ngens() == 1: if not F.is_zero(): raise ValueError("defining polynomial of curve must be zero " "if the ambient space is of dimension 1") A = AffineSpace(1, P.base_ring(), names=P.variable_names()) A._coordinate_ring = P else: raise TypeError("number of variables of F (={}) must be 2 or 3".format(F)) F = [F] else: raise TypeError("F (={}) must be a multivariate polynomial".format(F)) else: if not is_AmbientSpace(A): raise TypeError("ambient space must be either an affine or projective space") if not isinstance(F, (list, tuple)): F = [F] if not all(f.parent() == A.coordinate_ring() for f in F): raise TypeError("need a list of polynomials of the coordinate ring of {}".format(A)) n = A.dimension_relative() if n < 1: raise TypeError("ambient space should be an affine or projective space of positive dimension") k = A.base_ring() if is_AffineSpace(A): if n != 2: if is_FiniteField(k): if A.coordinate_ring().ideal(F).is_prime(): return IntegralAffineCurve_finite_field(A, F) if k in Fields(): if k == QQ and A.coordinate_ring().ideal(F).is_prime(): return IntegralAffineCurve(A, F) return AffineCurve_field(A, F) return AffineCurve(A, F) if not (len(F) == 1 and F[0] != 0 and F[0].degree() > 0): raise TypeError("need a single nonconstant polynomial to define a plane curve") F = F[0] if is_FiniteField(k): if _is_irreducible_and_reduced(F): return IntegralAffinePlaneCurve_finite_field(A, F) return AffinePlaneCurve_finite_field(A, F) if k in Fields(): if k == QQ and _is_irreducible_and_reduced(F): return IntegralAffinePlaneCurve(A, F) return AffinePlaneCurve_field(A, F) return AffinePlaneCurve(A, F) elif is_ProjectiveSpace(A): if n != 2: if not all(f.is_homogeneous() for f in F): raise TypeError("polynomials defining a curve in a projective space must be homogeneous") if is_FiniteField(k): if A.coordinate_ring().ideal(F).is_prime(): return IntegralProjectiveCurve_finite_field(A, F) if k in Fields(): if k == QQ and A.coordinate_ring().ideal(F).is_prime(): return IntegralProjectiveCurve(A, F) return ProjectiveCurve_field(A, F) return ProjectiveCurve(A, F) # There is no dimension check when initializing a plane curve, so check # here that F consists of a single nonconstant polynomial. if not (len(F) == 1 and F[0] != 0 and F[0].degree() > 0): raise TypeError("need a single nonconstant polynomial to define a plane curve") F = F[0] if not F.is_homogeneous(): raise TypeError("{} is not a homogeneous polynomial".format(F)) if is_FiniteField(k): if _is_irreducible_and_reduced(F): return IntegralProjectivePlaneCurve_finite_field(A, F) return ProjectivePlaneCurve_finite_field(A, F) if k in Fields(): if k == QQ and _is_irreducible_and_reduced(F): return IntegralProjectivePlaneCurve(A, F) return ProjectivePlaneCurve_field(A, F) return ProjectivePlaneCurve(A, F) else: raise TypeError('ambient space neither affine nor projective')
def Conic(base_field, F=None, names=None, unique=True): r""" Return the plane projective conic curve defined by ``F`` over ``base_field``. The input form ``Conic(F, names=None)`` is also accepted, in which case the fraction field of the base ring of ``F`` is used as base field. INPUT: - ``base_field`` -- The base field of the conic. - ``names`` -- a list, tuple, or comma separated string of three variable names specifying the names of the coordinate functions of the ambient space `\Bold{P}^3`. If not specified or read off from ``F``, then this defaults to ``'x,y,z'``. - ``F`` -- a polynomial, list, matrix, ternary quadratic form, or list or tuple of 5 points in the plane. If ``F`` is a polynomial or quadratic form, then the output is the curve in the projective plane defined by ``F = 0``. If ``F`` is a polynomial, then it must be a polynomial of degree at most 2 in 2 variables, or a homogeneous polynomial in of degree 2 in 3 variables. If ``F`` is a matrix, then the output is the zero locus of `(x,y,z) F (x,y,z)^t`. If ``F`` is a list of coefficients, then it has length 3 or 6 and gives the coefficients of the monomials `x^2, y^2, z^2` or all 6 monomials `x^2, xy, xz, y^2, yz, z^2` in lexicographic order. If ``F`` is a list of 5 points in the plane, then the output is a conic through those points. - ``unique`` -- Used only if ``F`` is a list of points in the plane. If the conic through the points is not unique, then raise ``ValueError`` if and only if ``unique`` is True OUTPUT: A plane projective conic curve defined by ``F`` over a field. EXAMPLES: Conic curves given by polynomials :: sage: X,Y,Z = QQ['X,Y,Z'].gens() sage: Conic(X^2 - X*Y + Y^2 - Z^2) Projective Conic Curve over Rational Field defined by X^2 - X*Y + Y^2 - Z^2 sage: x,y = GF(7)['x,y'].gens() sage: Conic(x^2 - x + 2*y^2 - 3, 'U,V,W') Projective Conic Curve over Finite Field of size 7 defined by U^2 + 2*V^2 - U*W - 3*W^2 Conic curves given by matrices :: sage: Conic(matrix(QQ, [[1, 2, 0], [4, 0, 0], [7, 0, 9]]), 'x,y,z') Projective Conic Curve over Rational Field defined by x^2 + 6*x*y + 7*x*z + 9*z^2 sage: x,y,z = GF(11)['x,y,z'].gens() sage: C = Conic(x^2+y^2-2*z^2); C Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2 sage: Conic(C.symmetric_matrix(), 'x,y,z') Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2 Conics given by coefficients :: sage: Conic(QQ, [1,2,3]) Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + 3*z^2 sage: Conic(GF(7), [1,2,3,4,5,6], 'X') Projective Conic Curve over Finite Field of size 7 defined by X0^2 + 2*X0*X1 - 3*X1^2 + 3*X0*X2 - 2*X1*X2 - X2^2 The conic through a set of points :: sage: C = Conic(QQ, [[10,2],[3,4],[-7,6],[7,8],[9,10]]); C Projective Conic Curve over Rational Field defined by x^2 + 13/4*x*y - 17/4*y^2 - 35/2*x*z + 91/4*y*z - 37/2*z^2 sage: C.rational_point() (10 : 2 : 1) sage: C.point([3,4]) (3 : 4 : 1) sage: a=AffineSpace(GF(13),2) sage: Conic([a([x,x^2]) for x in range(5)]) Projective Conic Curve over Finite Field of size 13 defined by x^2 - y*z """ if not (base_field is None or isinstance(base_field, IntegralDomain)): if names is None: names = F F = base_field base_field = None if isinstance(F, (list, tuple)): if len(F) == 1: return Conic(base_field, F[0], names) if names is None: names = 'x,y,z' if len(F) == 5: L = [] for f in F: if isinstance(f, SchemeMorphism_point_affine): C = Sequence(f, universe=base_field) if len(C) != 2: raise TypeError("points in F (=%s) must be planar" % F) C.append(1) elif isinstance(f, SchemeMorphism_point_projective_field): C = Sequence(f, universe=base_field) elif isinstance(f, (list, tuple)): C = Sequence(f, universe=base_field) if len(C) == 2: C.append(1) else: raise TypeError("F (=%s) must be a sequence of planar " \ "points" % F) if len(C) != 3: raise TypeError("points in F (=%s) must be planar" % F) P = C.universe() if not isinstance(P, IntegralDomain): raise TypeError("coordinates of points in F (=%s) must " \ "be in an integral domain" % F) L.append( Sequence([ C[0]**2, C[0] * C[1], C[0] * C[2], C[1]**2, C[1] * C[2], C[2]**2 ], P.fraction_field())) M = Matrix(L) if unique and M.rank() != 5: raise ValueError("points in F (=%s) do not define a unique " \ "conic" % F) con = Conic(base_field, Sequence(M.right_kernel().gen()), names) con.point(F[0]) return con F = Sequence(F, universe=base_field) base_field = F.universe().fraction_field() temp_ring = PolynomialRing(base_field, 3, names) (x, y, z) = temp_ring.gens() if len(F) == 3: return Conic(F[0] * x**2 + F[1] * y**2 + F[2] * z**2) if len(F) == 6: return Conic(F[0]*x**2 + F[1]*x*y + F[2]*x*z + F[3]*y**2 + \ F[4]*y*z + F[5]*z**2) raise TypeError("F (=%s) must be a sequence of 3 or 6" \ "coefficients" % F) if is_QuadraticForm(F): F = F.matrix() if is_Matrix(F) and F.is_square() and F.ncols() == 3: if names is None: names = 'x,y,z' temp_ring = PolynomialRing(F.base_ring(), 3, names) F = vector(temp_ring.gens()) * F * vector(temp_ring.gens()) if not is_MPolynomial(F): raise TypeError("F (=%s) must be a three-variable polynomial or " \ "a sequence of points or coefficients" % F) if F.total_degree() != 2: raise TypeError("F (=%s) must have degree 2" % F) if base_field is None: base_field = F.base_ring() if not isinstance(base_field, IntegralDomain): raise ValueError("Base field (=%s) must be a field" % base_field) base_field = base_field.fraction_field() if names is None: names = F.parent().variable_names() pol_ring = PolynomialRing(base_field, 3, names) if F.parent().ngens() == 2: (x, y, z) = pol_ring.gens() F = pol_ring(F(x / z, y / z) * z**2) if F == 0: raise ValueError("F must be nonzero over base field %s" % base_field) if F.total_degree() != 2: raise TypeError("F (=%s) must have degree 2 over base field %s" % \ (F, base_field)) if F.parent().ngens() == 3: P2 = ProjectiveSpace(2, base_field, names) if is_PrimeFiniteField(base_field): return ProjectiveConic_prime_finite_field(P2, F) if is_FiniteField(base_field): return ProjectiveConic_finite_field(P2, F) if is_RationalField(base_field): return ProjectiveConic_rational_field(P2, F) if is_NumberField(base_field): return ProjectiveConic_number_field(P2, F) if is_FractionField(base_field) and (is_PolynomialRing( base_field.ring()) or is_MPolynomialRing(base_field.ring())): return ProjectiveConic_rational_function_field(P2, F) return ProjectiveConic_field(P2, F) raise TypeError("Number of variables of F (=%s) must be 2 or 3" % F)
def Curve(F): """ Return the plane or space curve defined by `F`, where `F` can be either a multivariate polynomial, a list or tuple of polynomials, or an algebraic scheme. If `F` is in two variables the curve is affine, and if it is homogenous in `3` variables, then the curve is projective. EXAMPLE: A projective plane curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3); C Projective Curve over Rational Field defined by x^3 + y^3 + z^3 sage: C.genus() 1 EXAMPLE: Affine plane curves :: sage: x,y = GF(7)['x,y'].gens() sage: C = Curve(y^2 + x^3 + x^10); C Affine Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2 sage: C.genus() 0 sage: x, y = QQ['x,y'].gens() sage: Curve(x^3 + y^3 + 1) Affine Curve over Rational Field defined by x^3 + y^3 + 1 EXAMPLE: A projective space curve :: sage: x,y,z,w = QQ['x,y,z,w'].gens() sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C Projective Space Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4 sage: C.genus() 13 EXAMPLE: An affine space curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve([y^2 + x^3 + x^10 + z^7, x^2 + y^2]); C Affine Space Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2 sage: C.genus() 47 EXAMPLE: We can also make non-reduced non-irreducible curves. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve((x-y)*(x+y)) Projective Conic Curve over Rational Field defined by x^2 - y^2 sage: Curve((x-y)^2*(x+y)^2) Projective Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4 EXAMPLE: A union of curves is a curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3) sage: D = Curve(x^4 + y^4 + z^4) sage: C.union(D) Projective Curve over Rational Field defined by x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7 The intersection is not a curve, though it is a scheme. :: sage: X = C.intersection(D); X Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^3 + y^3 + z^3, x^4 + y^4 + z^4 Note that the intersection has dimension `0`. :: sage: X.dimension() 0 sage: I = X.defining_ideal(); I Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field EXAMPLE: In three variables, the defining equation must be homogeneous. If the parent polynomial ring is in three variables, then the defining ideal must be homogeneous. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve(x^2+y^2) Projective Conic Curve over Rational Field defined by x^2 + y^2 sage: Curve(x^2+y^2+z) Traceback (most recent call last): ... TypeError: x^2 + y^2 + z is not a homogeneous polynomial! The defining polynomial must always be nonzero:: sage: P1.<x,y> = ProjectiveSpace(1,GF(5)) sage: Curve(0*x) Traceback (most recent call last): ... ValueError: defining polynomial of curve must be nonzero """ if is_AlgebraicScheme(F): return Curve(F.defining_polynomials()) if isinstance(F, (list, tuple)): if len(F) == 1: return Curve(F[0]) F = Sequence(F) P = F.universe() if not is_MPolynomialRing(P): raise TypeError("universe of F must be a multivariate polynomial ring") for f in F: if not f.is_homogeneous(): A = AffineSpace(P.ngens(), P.base_ring()) A._coordinate_ring = P return AffineSpaceCurve_generic(A, F) A = ProjectiveSpace(P.ngens()-1, P.base_ring()) A._coordinate_ring = P return ProjectiveSpaceCurve_generic(A, F) if not is_MPolynomial(F): raise TypeError("F (=%s) must be a multivariate polynomial"%F) P = F.parent() k = F.base_ring() if F.parent().ngens() == 2: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") A2 = AffineSpace(2, P.base_ring()) A2._coordinate_ring = P if is_FiniteField(k): if k.is_prime_field(): return AffineCurve_prime_finite_field(A2, F) else: return AffineCurve_finite_field(A2, F) else: return AffineCurve_generic(A2, F) elif F.parent().ngens() == 3: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") P2 = ProjectiveSpace(2, P.base_ring()) P2._coordinate_ring = P if F.total_degree() == 2 and k.is_field(): return Conic(F) if is_FiniteField(k): if k.is_prime_field(): return ProjectiveCurve_prime_finite_field(P2, F) else: return ProjectiveCurve_finite_field(P2, F) else: return ProjectiveCurve_generic(P2, F) else: raise TypeError("Number of variables of F (=%s) must be 2 or 3"%F)
def EllipticCurve(x=None, y=None, j=None, minimal_twist=True): r""" Construct an elliptic curve. In Sage, an elliptic curve is always specified by its a-invariants .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. INPUT: There are several ways to construct an elliptic curve: - ``EllipticCurve([a1,a2,a3,a4,a6])``: Elliptic curve with given a-invariants. The invariants are coerced into the parent of the first element. If all are integers, they are coerced into the rational numbers. - ``EllipticCurve([a4,a6])``: Same as above, but `a_1=a_2=a_3=0`. - ``EllipticCurve(label)``: Returns the elliptic curve over Q from the Cremona database with the given label. The label is a string, such as ``"11a"`` or ``"37b2"``. The letters in the label *must* be lower case (Cremona's new labeling). - ``EllipticCurve(R, [a1,a2,a3,a4,a6])``: Create the elliptic curve over ``R`` with given a-invariants. Here ``R`` can be an arbitrary ring. Note that addition need not be defined. - ``EllipticCurve(j=j0)`` or ``EllipticCurve_from_j(j0)``: Return an elliptic curve with j-invariant ``j0``. - ``EllipticCurve(polynomial)``: Read off the a-invariants from the polynomial coefficients, see :func:`EllipticCurve_from_Weierstrass_polynomial`. In each case above where the input is a list of length 2 or 5, one can instead give a 2 or 5-tuple instead. EXAMPLES: We illustrate creating elliptic curves:: sage: EllipticCurve([0,0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field We create a curve from a Cremona label:: sage: EllipticCurve('37b2') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field sage: EllipticCurve('5077a') Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field sage: EllipticCurve('389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field Old Cremona labels are allowed:: sage: EllipticCurve('2400FF') Elliptic Curve defined by y^2 = x^3 + x^2 + 2*x + 8 over Rational Field Unicode labels are allowed:: sage: EllipticCurve(u'389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field We create curves over a finite field as follows:: sage: EllipticCurve([GF(5)(0),0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 sage: EllipticCurve(GF(5), [0, 0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type "elliptic curve over a finite field":: sage: F = Zmod(101) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 101 In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite are of type "generic elliptic curve":: sage: F = Zmod(95) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 95 The following is a curve over the complex numbers:: sage: E = EllipticCurve(CC, [0,0,1,-1,0]) sage: E Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision sage: E.j_invariant() 2988.97297297297 We can also create elliptic curves by giving the Weierstrass equation:: sage: x, y = var('x,y') sage: EllipticCurve(y^2 + y == x^3 + x - 9) Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field sage: R.<x,y> = GF(5)[] sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x) Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 2 over Finite Field of size 5 We can explicitly specify the `j`-invariant:: sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label() Elliptic Curve defined by y^2 = x^3 - x over Rational Field 1728 '32a2' sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant() Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5 2 See :trac:`6657` :: sage: EllipticCurve(GF(144169),j=1728) Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169 By default, when a rational value of `j` is given, the constructed curve is a minimal twist (minimal conductor for curves with that `j`-invariant). This can be changed by setting the optional parameter ``minimal_twist``, which is True by default, to False:: sage: EllipticCurve(j=100) Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field sage: E =EllipticCurve(j=100); E Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field sage: E.conductor() 33129800 sage: E.j_invariant() 100 sage: E =EllipticCurve(j=100, minimal_twist=False); E Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field sage: E.conductor() 298168200 sage: E.j_invariant() 100 Without this option, constructing the curve could take a long time since both `j` and `j-1728` have to be factored to compute the minimal twist (see :trac:`13100`):: sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False) sage: E.j_invariant() == 2^256+1 True TESTS:: sage: R = ZZ['u', 'v'] sage: EllipticCurve(R, [1,1]) Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v over Integer Ring We create a curve and a point over QQbar (see #6879):: sage: E = EllipticCurve(QQbar,[0,1]) sage: E(0) (0 : 1 : 0) sage: E.base_field() Algebraic Field sage: E = EllipticCurve(RR,[1,2]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: EllipticCurve(CC,[3,4]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field Algebraic Field See :trac:`6657` :: sage: EllipticCurve(3,j=1728) Traceback (most recent call last): ... ValueError: First parameter (if present) must be a ring when j is specified sage: EllipticCurve(GF(5),j=3/5) Traceback (most recent call last): ... ValueError: First parameter must be a ring containing 3/5 If the universe of the coefficients is a general field, the object constructed has type EllipticCurve_field. Otherwise it is EllipticCurve_generic. See :trac:`9816` :: sage: E = EllipticCurve([QQbar(1),3]); E Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([RR(1),3]); E Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([i,i]); E Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Symbolic Ring sage: SR in Fields() True sage: F = FractionField(PolynomialRing(QQ,'t')) sage: t = F.gen() sage: E = EllipticCurve([t,0]); E Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field See :trac:`12517`:: sage: E = EllipticCurve([1..5]) sage: EllipticCurve(E.a_invariants()) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field See :trac:`11773`:: sage: E = EllipticCurve() Traceback (most recent call last): ... TypeError: invalid input to EllipticCurve constructor """ import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field # here to avoid circular includes if j is not None: if not x is None: if is_Ring(x): try: j = x(j) except (ZeroDivisionError, ValueError, TypeError): raise ValueError, "First parameter must be a ring containing %s"%j else: raise ValueError, "First parameter (if present) must be a ring when j is specified" return EllipticCurve_from_j(j, minimal_twist) if x is None: raise TypeError, "invalid input to EllipticCurve constructor" if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if is_MPolynomial(x): if y is None: return EllipticCurve_from_Weierstrass_polynomial(x) else: return EllipticCurve_from_cubic(x, y, morphism=False) if is_Ring(x): if is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif is_FiniteField(x) or (is_IntegerModRing(x) and x.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_pAdicField(x): return ell_padic_field.EllipticCurve_padic_field(x, y) elif is_NumberField(x): return ell_number_field.EllipticCurve_number_field(x, y) elif x in _Fields: return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y) if isinstance(x, unicode): x = str(x) if isinstance(x, basestring): return ell_rational_field.EllipticCurve_rational_field(x) if is_RingElement(x) and y is None: raise TypeError, "invalid input to EllipticCurve constructor" if not isinstance(x, (list, tuple)): raise TypeError, "invalid input to EllipticCurve constructor" x = Sequence(x) if not (len(x) in [2,5]): raise ValueError, "sequence of coefficients must have length 2 or 5" R = x.universe() if isinstance(x[0], (rings.Rational, rings.Integer, int, long)): return ell_rational_field.EllipticCurve_rational_field(x, y) elif is_NumberField(R): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_pAdicField(R): return ell_padic_field.EllipticCurve_padic_field(x, y) elif is_FiniteField(R) or (is_IntegerModRing(R) and R.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif R in _Fields: return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y)
def _element_constructor_(self, x, n=0): r""" Construct a Laurent series from `x`. INPUT: - ``x`` -- object that can be converted into a Laurent series - ``n`` -- (default: 0) multiply the result by `t^n` EXAMPLES:: sage: R.<u> = LaurentSeriesRing(Qp(5, 10)) sage: S.<t> = LaurentSeriesRing(RationalField()) sage: print R(t + t^2 + O(t^3)) (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3) Note that coercing an element into its own parent just produces that element again (since Laurent series are immutable):: sage: u is R(u) True Rational functions are accepted:: sage: I = sqrt(-1) sage: K.<I> = QQ[I] sage: P.<t> = PolynomialRing(K) sage: L.<u> = LaurentSeriesRing(QQ[I]) sage: L((t*I)/(t^3+I*2*t)) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) :: sage: L(t*I) / L(t^3+I*2*t) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) TESTS: When converting from `R((z))` to `R((z))((w))`, the variable `z` is sent to `z` rather than to `w` (see :trac:`7085`):: sage: A.<z> = LaurentSeriesRing(QQ) sage: B.<w> = LaurentSeriesRing(A) sage: B(z) z sage: z/w z*w^-1 Various conversions from PARI (see also :trac:`2508`):: sage: L.<q> = LaurentSeriesRing(QQ) sage: L.set_default_prec(10) sage: L(pari('1/x')) q^-1 sage: L(pari('poltchebi(5)')) 5*q - 20*q^3 + 16*q^5 sage: L(pari('poltchebi(5) - 1/x^4')) -q^-4 + 5*q - 20*q^3 + 16*q^5 sage: L(pari('1/poltchebi(5)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9) sage: L(pari('poltchebi(5) + O(x^40)')) 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)')) -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('1/poltchebi(5) + O(x^10)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10) sage: L(pari('1/poltchebi(5) + O(x^10)'), -10) # Multiply by q^-10 1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1) sage: L(pari('O(x^-10)')) O(q^-10) """ from sage.rings.fraction_field_element import is_FractionFieldElement from sage.rings.polynomial.polynomial_element import is_Polynomial from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial from sage.structure.element import parent P = parent(x) if isinstance(x, self.element_class) and n == 0 and P is self: return x # ok, since Laurent series are immutable (no need to make a copy) elif P is self.base_ring(): # Convert x into a power series; if P is itself a Laurent # series ring A((t)), this prevents the implementation of # LaurentSeries.__init__() from effectively applying the # ring homomorphism A((t)) -> A((t))((u)) sending t to u # instead of the one sending t to t. We cannot easily # tell LaurentSeries.__init__() to be more strict, because # A((t)) -> B((u)) is expected to send t to u if A admits # a coercion to B but A((t)) does not, and this condition # would be inefficient to check there. x = self.power_series_ring()(x) elif isinstance(x, pari_gen): t = x.type() if t == "t_RFRAC": # Rational function x = self(self.polynomial_ring()(x.numerator())) / \ self(self.polynomial_ring()(x.denominator())) return (x << n) elif t == "t_SER": # Laurent series n += x._valp() bigoh = n + x.length() x = self(self.polynomial_ring()(x.Vec())) return (x << n).add_bigoh(bigoh) else: # General case, pretend to be a polynomial return self(self.polynomial_ring()(x)) << n elif is_FractionFieldElement(x) and \ (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \ (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())): x = self(x.numerator()) / self(x.denominator()) return (x << n) return self.element_class(self, x, n)
def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True, **kwds): """ Return a ``UniqueFactory`` key and possibly extra parameters. INPUT: See the documentation for :class:`EllipticCurveFactory`. OUTPUT: A pair ``(key, extra_args)``: - ``key`` has the form `(R, (a_1, a_2, a_3, a_4, a_6))`, representing a ring and the Weierstrass coefficients of an elliptic curve over that ring; - ``extra_args`` is a dictionary containing additional data to be inserted into the elliptic curve structure. EXAMPLES:: sage: EllipticCurve.create_key_and_extra_args(j=8000) ((Rational Field, (0, -1, 0, -3, -1)), {}) When constructing a curve over `\\QQ` from a Cremona or LMFDB label, the invariants from the database are returned as ``extra_args``:: sage: key, data = EllipticCurve.create_key_and_extra_args('389.a1') sage: key (Rational Field, (0, 1, 1, -2, 0)) sage: data['conductor'] 389 sage: data['cremona_label'] '389a1' sage: data['lmfdb_label'] '389.a1' sage: data['rank'] 2 sage: data['torsion_order'] 1 User-specified keywords are also included in ``extra_args``:: sage: key, data = EllipticCurve.create_key_and_extra_args((0, 0, 1, -23737, 960366), rank=4) sage: data['rank'] 4 Furthermore, keywords takes precedence over data from the database, which can be used to specify an alternative set of generators for the Mordell-Weil group:: sage: key, data = EllipticCurve.create_key_and_extra_args('5077a1', gens=[[1, -1], [-2, 3], [4, -7]]) sage: data['gens'] [[1, -1], [-2, 3], [4, -7]] sage: E = EllipticCurve.create_object(0, key, **data) sage: E.gens() [(-2 : 3 : 1), (1 : -1 : 1), (4 : -7 : 1)] Note that elliptic curves are equal if and only they have the same base ring and Weierstrass equation; the data in ``extra_args`` do not influence comparison of elliptic curves. A consequence of this is that passing keyword arguments only works when constructing an elliptic curve the first time:: sage: E = EllipticCurve('433a1', gens=[[-1, 1], [3, 4]]) sage: E.gens() [(-1 : 1 : 1), (3 : 4 : 1)] sage: E = EllipticCurve('433a1', gens=[[-1, 0], [0, 1]]) sage: E.gens() [(-1 : 1 : 1), (3 : 4 : 1)] .. WARNING:: Manually specifying extra data is almost never necessary and is not guaranteed to have any effect, as the above example shows. Almost no checking is done, so specifying incorrect data may lead to wrong results of computations instead of errors or warnings. """ R = None if is_Ring(x): (R, x) = (x, y) if j is not None: if R is not None: try: j = R(j) except (ZeroDivisionError, ValueError, TypeError): raise ValueError( "First parameter must be a ring containing %s" % j) elif x is not None: raise ValueError( "First parameter (if present) must be a ring when j is specified" ) x = coefficients_from_j(j, minimal_twist) if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if is_MPolynomial(x): if y is None: x = coefficients_from_Weierstrass_polynomial(x) else: x = coefficients_from_cubic(x, y, morphism=False) if isinstance(x, string_types): # Interpret x as a Cremona or LMFDB label. from sage.databases.cremona import CremonaDatabase x, data = CremonaDatabase().coefficients_and_data(x) # User-provided keywords may override database entries. data.update(kwds) kwds = data if not isinstance(x, (list, tuple)): raise TypeError("invalid input to EllipticCurve constructor") if len(x) == 2: x = (0, 0, 0, x[0], x[1]) elif len(x) != 5: raise ValueError( "sequence of coefficients must have length 2 or 5") if R is None: R = Sequence(x).universe() if R in (rings.ZZ, ) + integer_types: R = rings.QQ return (R, tuple(R(a) for a in x)), kwds
def __call__(self, x, n=0): r""" Coerces the element x into this Laurent series ring. INPUT: - ``x`` - the element to coerce - ``n`` - the result of the coercion will be multiplied by `t^n` (default: 0) EXAMPLES:: sage: R.<u> = LaurentSeriesRing(Qp(5, 10)) sage: S.<t> = LaurentSeriesRing(RationalField()) sage: print R(t + t^2 + O(t^3)) (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3) Note that coercing an element into its own parent just produces that element again (since Laurent series are immutable):: sage: u is R(u) True Rational functions are accepted:: sage: I = sqrt(-1) sage: K.<I> = QQ[I] sage: P.<t> = PolynomialRing(K) sage: L.<u> = LaurentSeriesRing(QQ[I]) sage: L((t*I)/(t^3+I*2*t)) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) :: sage: L(t*I) / L(t^3+I*2*t) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) Various conversions from PARI (see also #2508):: sage: L.<q> = LaurentSeriesRing(QQ) sage: L.set_default_prec(10) sage: L(pari('1/x')) q^-1 sage: L(pari('poltchebi(5)')) 5*q - 20*q^3 + 16*q^5 sage: L(pari('poltchebi(5) - 1/x^4')) -q^-4 + 5*q - 20*q^3 + 16*q^5 sage: L(pari('1/poltchebi(5)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9) sage: L(pari('poltchebi(5) + O(x^40)')) 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)')) -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('1/poltchebi(5) + O(x^10)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10) sage: L(pari('1/poltchebi(5) + O(x^10)'), -10) # Multiply by q^-10 1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1) sage: L(pari('O(x^-10)')) O(q^-10) """ from sage.rings.fraction_field_element import is_FractionFieldElement from sage.rings.polynomial.polynomial_element import is_Polynomial from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial if isinstance(x, laurent_series_ring_element.LaurentSeries ) and n == 0 and self is x.parent(): return x # ok, since Laurent series are immutable (no need to make a copy) elif isinstance(x, pari_gen): t = x.type() if t == "t_RFRAC": # Rational function x = self(self.polynomial_ring()(x.numerator())) / \ self(self.polynomial_ring()(x.denominator())) return (x << n) elif t == "t_SER": # Laurent series n += x._valp() bigoh = n + x.length() x = self(self.polynomial_ring()(x.Vec())) return (x << n).add_bigoh(bigoh) else: # General case, pretend to be a polynomial return self(self.polynomial_ring()(x)) << n elif is_FractionFieldElement(x) and \ (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \ (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())): x = self(x.numerator()) / self(x.denominator()) return (x << n) else: return laurent_series_ring_element.LaurentSeries(self, x, n)
def Curve(F, A=None): """ Return the plane or space curve defined by ``F``, where ``F`` can be either a multivariate polynomial, a list or tuple of polynomials, or an algebraic scheme. If no ambient space is passed in for ``A``, and if ``F`` is not an algebraic scheme, a new ambient space is constructed. Also not specifying an ambient space will cause the curve to be defined in either affine or projective space based on properties of ``F``. In particular, if ``F`` contains a nonhomogenous polynomial, the curve is affine, and if ``F`` consists of homogenous polynomials, then the curve is projective. INPUT: - ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme. - ``A`` -- (default: None) an ambient space in which to create the curve. EXAMPLES: A projective plane curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3); C Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3 sage: C.genus() 1 EXAMPLES: Affine plane curves :: sage: x,y = GF(7)['x,y'].gens() sage: C = Curve(y^2 + x^3 + x^10); C Affine Plane Curve over Finite Field of size 7 defined by x^10 + x^3 + y^2 sage: C.genus() 0 sage: x, y = QQ['x,y'].gens() sage: Curve(x^3 + y^3 + 1) Affine Plane Curve over Rational Field defined by x^3 + y^3 + 1 EXAMPLES: A projective space curve :: sage: x,y,z,w = QQ['x,y,z,w'].gens() sage: C = Curve([x^3 + y^3 - z^3 - w^3, x^5 - y*z^4]); C Projective Curve over Rational Field defined by x^3 + y^3 - z^3 - w^3, x^5 - y*z^4 sage: C.genus() 13 EXAMPLES: An affine space curve :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve([y^2 + x^3 + x^10 + z^7, x^2 + y^2]); C Affine Curve over Rational Field defined by x^10 + z^7 + x^3 + y^2, x^2 + y^2 sage: C.genus() 47 EXAMPLES: We can also make non-reduced non-irreducible curves. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve((x-y)*(x+y)) Projective Conic Curve over Rational Field defined by x^2 - y^2 sage: Curve((x-y)^2*(x+y)^2) Projective Plane Curve over Rational Field defined by x^4 - 2*x^2*y^2 + y^4 EXAMPLES: A union of curves is a curve. :: sage: x,y,z = QQ['x,y,z'].gens() sage: C = Curve(x^3 + y^3 + z^3) sage: D = Curve(x^4 + y^4 + z^4) sage: C.union(D) Projective Plane Curve over Rational Field defined by x^7 + x^4*y^3 + x^3*y^4 + y^7 + x^4*z^3 + y^4*z^3 + x^3*z^4 + y^3*z^4 + z^7 The intersection is not a curve, though it is a scheme. :: sage: X = C.intersection(D); X Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^3 + y^3 + z^3, x^4 + y^4 + z^4 Note that the intersection has dimension `0`. :: sage: X.dimension() 0 sage: I = X.defining_ideal(); I Ideal (x^3 + y^3 + z^3, x^4 + y^4 + z^4) of Multivariate Polynomial Ring in x, y, z over Rational Field EXAMPLES: In three variables, the defining equation must be homogeneous. If the parent polynomial ring is in three variables, then the defining ideal must be homogeneous. :: sage: x,y,z = QQ['x,y,z'].gens() sage: Curve(x^2+y^2) Projective Conic Curve over Rational Field defined by x^2 + y^2 sage: Curve(x^2+y^2+z) Traceback (most recent call last): ... TypeError: x^2 + y^2 + z is not a homogeneous polynomial The defining polynomial must always be nonzero:: sage: P1.<x,y> = ProjectiveSpace(1,GF(5)) sage: Curve(0*x) Traceback (most recent call last): ... ValueError: defining polynomial of curve must be nonzero :: sage: A.<x,y,z> = AffineSpace(QQ, 3) sage: C = Curve([y - x^2, z - x^3], A) sage: A == C.ambient_space() True """ if not A is None: if not isinstance(F, (list, tuple)): return Curve([F], A) if not is_AmbientSpace(A): raise TypeError("A (=%s) must be either an affine or projective space"%A) if not all([f.parent() == A.coordinate_ring() for f in F]): raise TypeError("F (=%s) must be a list or tuple of polynomials of the coordinate ring of " \ "A (=%s)"%(F, A)) n = A.dimension_relative() if n < 2: raise TypeError("A (=%s) must be either an affine or projective space of dimension > 1"%A) # there is no dimension check when initializing a plane curve, so check here that F consists # of a single nonconstant polynomial if n == 2: if len(F) != 1 or F[0] == 0 or not is_MPolynomial(F[0]): raise TypeError("F (=%s) must consist of a single nonconstant polynomial to define a plane curve"%(F,)) if is_AffineSpace(A): if n > 2: return AffineCurve(A, F) k = A.base_ring() if is_FiniteField(k): if k.is_prime_field(): return AffinePlaneCurve_prime_finite_field(A, F[0]) return AffinePlaneCurve_finite_field(A, F[0]) return AffinePlaneCurve(A, F[0]) elif is_ProjectiveSpace(A): if not all([f.is_homogeneous() for f in F]): raise TypeError("polynomials defining a curve in a projective space must be homogeneous") if n > 2: return ProjectiveCurve(A, F) k = A.base_ring() if is_FiniteField(k): if k.is_prime_field(): return ProjectivePlaneCurve_prime_finite_field(A, F[0]) return ProjectivePlaneCurve_finite_field(A, F[0]) return ProjectivePlaneCurve(A, F[0]) if is_AlgebraicScheme(F): return Curve(F.defining_polynomials(), F.ambient_space()) if isinstance(F, (list, tuple)): if len(F) == 1: return Curve(F[0]) F = Sequence(F) P = F.universe() if not is_MPolynomialRing(P): raise TypeError("universe of F must be a multivariate polynomial ring") for f in F: if not f.is_homogeneous(): A = AffineSpace(P.ngens(), P.base_ring()) A._coordinate_ring = P return AffineCurve(A, F) A = ProjectiveSpace(P.ngens()-1, P.base_ring()) A._coordinate_ring = P return ProjectiveCurve(A, F) if not is_MPolynomial(F): raise TypeError("F (=%s) must be a multivariate polynomial"%F) P = F.parent() k = F.base_ring() if F.parent().ngens() == 2: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") A2 = AffineSpace(2, P.base_ring()) A2._coordinate_ring = P if is_FiniteField(k): if k.is_prime_field(): return AffinePlaneCurve_prime_finite_field(A2, F) else: return AffinePlaneCurve_finite_field(A2, F) else: return AffinePlaneCurve(A2, F) elif F.parent().ngens() == 3: if F == 0: raise ValueError("defining polynomial of curve must be nonzero") P2 = ProjectiveSpace(2, P.base_ring()) P2._coordinate_ring = P if F.total_degree() == 2 and k.is_field(): return Conic(F) if is_FiniteField(k): if k.is_prime_field(): return ProjectivePlaneCurve_prime_finite_field(P2, F) else: return ProjectivePlaneCurve_finite_field(P2, F) else: return ProjectivePlaneCurve(P2, F) else: raise TypeError("Number of variables of F (=%s) must be 2 or 3"%F)
def _element_constructor_(self, x, n=0): r""" Construct a Laurent series from `x`. INPUT: - ``x`` -- object that can be converted into a Laurent series - ``n`` -- (default: 0) multiply the result by `t^n` EXAMPLES:: sage: R.<u> = LaurentSeriesRing(Qp(5, 10)) sage: S.<t> = LaurentSeriesRing(RationalField()) sage: print R(t + t^2 + O(t^3)) (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3) Note that coercing an element into its own parent just produces that element again (since Laurent series are immutable):: sage: u is R(u) True Rational functions are accepted:: sage: I = sqrt(-1) sage: K.<I> = QQ[I] sage: P.<t> = PolynomialRing(K) sage: L.<u> = LaurentSeriesRing(QQ[I]) sage: L((t*I)/(t^3+I*2*t)) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) :: sage: L(t*I) / L(t^3+I*2*t) 1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 + 1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 + 1/1024*I*u^18 + O(u^20) TESTS: When converting from `R((z))` to `R((z))((w))`, the variable `z` is sent to `z` rather than to `w` (see :trac:`7085`):: sage: A.<z> = LaurentSeriesRing(QQ) sage: B.<w> = LaurentSeriesRing(A) sage: B(z) z sage: z/w z*w^-1 Various conversions from PARI (see also :trac:`2508`):: sage: L.<q> = LaurentSeriesRing(QQ) sage: L.set_default_prec(10) doctest:...: DeprecationWarning: This method is deprecated. See http://trac.sagemath.org/16201 for details. sage: L(pari('1/x')) q^-1 sage: L(pari('polchebyshev(5)')) 5*q - 20*q^3 + 16*q^5 sage: L(pari('polchebyshev(5) - 1/x^4')) -q^-4 + 5*q - 20*q^3 + 16*q^5 sage: L(pari('1/polchebyshev(5)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9) sage: L(pari('polchebyshev(5) + O(x^40)')) 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('polchebyshev(5) - 1/x^4 + O(x^40)')) -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40) sage: L(pari('1/polchebyshev(5) + O(x^10)')) 1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10) sage: L(pari('1/polchebyshev(5) + O(x^10)'), -10) # Multiply by q^-10 1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1) sage: L(pari('O(x^-10)')) O(q^-10) """ from sage.rings.fraction_field_element import is_FractionFieldElement from sage.rings.polynomial.polynomial_element import is_Polynomial from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial from sage.structure.element import parent P = parent(x) if isinstance(x, self.element_class) and n==0 and P is self: return x # ok, since Laurent series are immutable (no need to make a copy) elif P is self.base_ring(): # Convert x into a power series; if P is itself a Laurent # series ring A((t)), this prevents the implementation of # LaurentSeries.__init__() from effectively applying the # ring homomorphism A((t)) -> A((t))((u)) sending t to u # instead of the one sending t to t. We cannot easily # tell LaurentSeries.__init__() to be more strict, because # A((t)) -> B((u)) is expected to send t to u if A admits # a coercion to B but A((t)) does not, and this condition # would be inefficient to check there. x = self.power_series_ring()(x) elif isinstance(x, pari_gen): t = x.type() if t == "t_RFRAC": # Rational function x = self(self.polynomial_ring()(x.numerator())) / \ self(self.polynomial_ring()(x.denominator())) return (x << n) elif t == "t_SER": # Laurent series n += x._valp() bigoh = n + x.length() x = self(self.polynomial_ring()(x.Vec())) return (x << n).add_bigoh(bigoh) else: # General case, pretend to be a polynomial return self(self.polynomial_ring()(x)) << n elif is_FractionFieldElement(x) and \ (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \ (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())): x = self(x.numerator())/self(x.denominator()) return (x << n) return self.element_class(self, x, n)
def EllipticCurve(x=None, y=None, j=None, minimal_twist=True): r""" Construct an elliptic curve. In Sage, an elliptic curve is always specified by its a-invariants .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. INPUT: There are several ways to construct an elliptic curve: - ``EllipticCurve([a1,a2,a3,a4,a6])``: Elliptic curve with given a-invariants. The invariants are coerced into the parent of the first element. If all are integers, they are coerced into the rational numbers. - ``EllipticCurve([a4,a6])``: Same as above, but `a_1=a_2=a_3=0`. - ``EllipticCurve(label)``: Returns the elliptic curve over Q from the Cremona database with the given label. The label is a string, such as ``"11a"`` or ``"37b2"``. The letters in the label *must* be lower case (Cremona's new labeling). - ``EllipticCurve(R, [a1,a2,a3,a4,a6])``: Create the elliptic curve over ``R`` with given a-invariants. Here ``R`` can be an arbitrary ring. Note that addition need not be defined. - ``EllipticCurve(j=j0)`` or ``EllipticCurve_from_j(j0)``: Return an elliptic curve with j-invariant ``j0``. - ``EllipticCurve(polynomial)``: Read off the a-invariants from the polynomial coefficients, see :func:`EllipticCurve_from_Weierstrass_polynomial`. In each case above where the input is a list of length 2 or 5, one can instead give a 2 or 5-tuple instead. EXAMPLES: We illustrate creating elliptic curves:: sage: EllipticCurve([0,0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field We create a curve from a Cremona label:: sage: EllipticCurve('37b2') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field sage: EllipticCurve('5077a') Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field sage: EllipticCurve('389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field Old Cremona labels are allowed:: sage: EllipticCurve('2400FF') Elliptic Curve defined by y^2 = x^3 + x^2 + 2*x + 8 over Rational Field Unicode labels are allowed:: sage: EllipticCurve(u'389a') Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field We create curves over a finite field as follows:: sage: EllipticCurve([GF(5)(0),0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 sage: EllipticCurve(GF(5), [0, 0,1,-1,0]) Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5 Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type "elliptic curve over a finite field":: sage: F = Zmod(101) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 101 In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite are of type "generic elliptic curve":: sage: F = Zmod(95) sage: EllipticCurve(F, [2, 3]) Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95 sage: E = EllipticCurve([F(2), F(3)]) sage: type(E) <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'> sage: E.category() Category of schemes over Ring of integers modulo 95 The following is a curve over the complex numbers:: sage: E = EllipticCurve(CC, [0,0,1,-1,0]) sage: E Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision sage: E.j_invariant() 2988.97297297297 We can also create elliptic curves by giving the Weierstrass equation:: sage: x, y = var('x,y') sage: EllipticCurve(y^2 + y == x^3 + x - 9) Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field sage: R.<x,y> = GF(5)[] sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x) Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 2 over Finite Field of size 5 We can explicitly specify the `j`-invariant:: sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label() Elliptic Curve defined by y^2 = x^3 - x over Rational Field 1728 '32a2' sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant() Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5 2 See :trac:`6657` :: sage: EllipticCurve(GF(144169),j=1728) Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169 By default, when a rational value of `j` is given, the constructed curve is a minimal twist (minimal conductor for curves with that `j`-invariant). This can be changed by setting the optional parameter ``minimal_twist``, which is True by default, to False:: sage: EllipticCurve(j=100) Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field sage: E =EllipticCurve(j=100); E Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field sage: E.conductor() 33129800 sage: E.j_invariant() 100 sage: E =EllipticCurve(j=100, minimal_twist=False); E Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field sage: E.conductor() 298168200 sage: E.j_invariant() 100 Without this option, constructing the curve could take a long time since both `j` and `j-1728` have to be factored to compute the minimal twist (see :trac:`13100`):: sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False) sage: E.j_invariant() == 2^256+1 True TESTS:: sage: R = ZZ['u', 'v'] sage: EllipticCurve(R, [1,1]) Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v over Integer Ring We create a curve and a point over QQbar (see #6879):: sage: E = EllipticCurve(QQbar,[0,1]) sage: E(0) (0 : 1 : 0) sage: E.base_field() Algebraic Field sage: E = EllipticCurve(RR,[1,2]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: EllipticCurve(CC,[3,4]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision Real Field with 53 bits of precision sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field() Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field Algebraic Field See :trac:`6657` :: sage: EllipticCurve(3,j=1728) Traceback (most recent call last): ... ValueError: First parameter (if present) must be a ring when j is specified sage: EllipticCurve(GF(5),j=3/5) Traceback (most recent call last): ... ValueError: First parameter must be a ring containing 3/5 If the universe of the coefficients is a general field, the object constructed has type EllipticCurve_field. Otherwise it is EllipticCurve_generic. See :trac:`9816` :: sage: E = EllipticCurve([QQbar(1),3]); E Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([RR(1),3]); E Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E = EllipticCurve([i,i]); E Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Symbolic Ring sage: SR in Fields() True sage: F = FractionField(PolynomialRing(QQ,'t')) sage: t = F.gen() sage: E = EllipticCurve([t,0]); E Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field sage: type(E) <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'> sage: E.category() Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field See :trac:`12517`:: sage: E = EllipticCurve([1..5]) sage: EllipticCurve(E.a_invariants()) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field See :trac:`11773`:: sage: E = EllipticCurve() Traceback (most recent call last): ... TypeError: invalid input to EllipticCurve constructor """ import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field # here to avoid circular includes if j is not None: if not x is None: if is_Ring(x): try: j = x(j) except (ZeroDivisionError, ValueError, TypeError): raise ValueError, "First parameter must be a ring containing %s" % j else: raise ValueError, "First parameter (if present) must be a ring when j is specified" return EllipticCurve_from_j(j, minimal_twist) if x is None: raise TypeError, "invalid input to EllipticCurve constructor" if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if is_MPolynomial(x): if y is None: return EllipticCurve_from_Weierstrass_polynomial(x) else: return EllipticCurve_from_cubic(x, y, morphism=False) if is_Ring(x): if is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif is_FiniteField(x) or (is_IntegerModRing(x) and x.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_pAdicField(x): return ell_padic_field.EllipticCurve_padic_field(x, y) elif is_NumberField(x): return ell_number_field.EllipticCurve_number_field(x, y) elif x in _Fields: return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y) if isinstance(x, unicode): x = str(x) if isinstance(x, basestring): return ell_rational_field.EllipticCurve_rational_field(x) if is_RingElement(x) and y is None: raise TypeError, "invalid input to EllipticCurve constructor" if not isinstance(x, (list, tuple)): raise TypeError, "invalid input to EllipticCurve constructor" x = Sequence(x) if not (len(x) in [2, 5]): raise ValueError, "sequence of coefficients must have length 2 or 5" R = x.universe() if isinstance(x[0], (rings.Rational, rings.Integer, int, long)): return ell_rational_field.EllipticCurve_rational_field(x, y) elif is_NumberField(R): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_pAdicField(R): return ell_padic_field.EllipticCurve_padic_field(x, y) elif is_FiniteField(R) or (is_IntegerModRing(R) and R.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif R in _Fields: return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y)