def rational_points(self, F=None): """ Return the list of `F`-rational points on the affine space self, where `F` is a given finite field, or the base ring of self. EXAMPLES:: sage: A = AffineSpace(1, GF(3)) sage: A.rational_points() [(0), (1), (2)] sage: A.rational_points(GF(3^2, 'b')) [(0), (2*b), (b + 1), (b + 2), (2), (b), (2*b + 2), (2*b + 1), (1)] sage: AffineSpace(2, ZZ).rational_points(GF(2)) [(0, 0), (1, 0), (0, 1), (1, 1)] TESTS:: sage: AffineSpace(2, QQ).rational_points() Traceback (most recent call last): ... TypeError: Base ring (= Rational Field) must be a finite field. sage: AffineSpace(1, GF(3)).rational_points(ZZ) Traceback (most recent call last): ... TypeError: Second argument (= Integer Ring) must be a finite field. """ if F == None: if not is_FiniteField(self.base_ring()): raise TypeError, "Base ring (= %s) must be a finite field."%self.base_ring() return [ P for P in self ] elif not is_FiniteField(F): raise TypeError, "Second argument (= %s) must be a finite field."%F return [ P for P in self.base_extend(F) ]
def SU(n, R, var='a'): """ The special unitary group `SU( d, R )` consists of all `d \times d` matrices that preserve a nondegenerate sequilinear form over the ring `R` and have determinant one. .. note:: For a finite field the matrices that preserve a sesquilinear form over `F_q` live over `F_{q^2}`. So ``SU(n,q)`` for integer ``q`` constructs the matrix group over the base ring ``GF(q^2)``. .. note:: This group is also available via ``groups.matrix.SU()``. INPUT: - ``n`` -- a positive integer. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``var`` -- variable used to represent generator of the finite field, if needed. OUTPUT: Return the special unitary group. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3, GF(5)) Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3,QQ) Special Unitary Group of degree 3 over Rational Field TESTS:: sage: groups.matrix.SU(2, 3) Special Unitary Group of degree 2 over Finite Field in a of size 3^2 """ degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q ** 2, name=var) name = 'Special Unitary Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{SU}}_{{{0}}}({1})'.format(degree, latex(ring)) if is_FiniteField(ring): cmd = 'SU({0}, {1})'.format(degree, q) return UnitaryMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, True, name, ltx)
def Sp(n, R, var='a'): """ Return the symplectic group of degree n over R. .. note:: This group is also available via ``groups.matrix.Sp()``. EXAMPLES:: sage: Sp(4,5) Symplectic Group of rank 2 over Finite Field of size 5 sage: Sp(3,GF(7)) Traceback (most recent call last): ... ValueError: the degree n (=3) must be even TESTS:: sage: groups.matrix.Sp(2, 3) Symplectic Group of rank 1 over Finite Field of size 3 """ if n%2!=0: raise ValueError, "the degree n (=%s) must be even"%n if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if is_FiniteField(R): return SymplecticGroup_finite_field(n, R) else: return SymplecticGroup_generic(n, R)
def points(self, B=0): """ Return some or all rational points of a projective scheme. INPUT: - `B` -- integer (optional, default=0). The bound for the coordinates. OUTPUT: A list of points. Over a finite field, all points are returned. Over an infinite field, all points satisfying the bound are returned. EXAMPLES:: sage: P1 = ProjectiveSpace(GF(2),1) sage: F.<a> = GF(4,'a') sage: P1(F).points() [(0 : 1), (1 : 0), (1 : 1), (a : 1), (a + 1 : 1)] """ from sage.schemes.generic.rational_point import enum_projective_rational_field from sage.schemes.generic.rational_point import enum_projective_finite_field R = self.value_ring() if is_RationalField(R): if not B > 0: raise TypeError, "A positive bound B (= %s) must be specified."%B return enum_projective_rational_field(self,B) elif is_FiniteField(R): return enum_projective_finite_field(self.extended_codomain()) else: raise TypeError, "Unable to enumerate points over %s."%R
def SU(n, F, var='a'): """ Return the special unitary group of degree `n` over `F`. .. note:: This group is also available via ``groups.matrix.SU()``. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field of size 5 sage: SU(3,QQ) Traceback (most recent call last): ... NotImplementedError: special unitary group only implemented over finite fields TESTS:: sage: groups.matrix.SU(2, 3) Special Unitary Group of degree 2 over Finite Field of size 3 """ if isinstance(F, (int, long, Integer)): F = GF(F, var) if is_FiniteField(F): return SpecialUnitaryGroup_finite_field(n, F, var=var) else: raise NotImplementedError, "special unitary group only implemented over finite fields"
def Sp(n, R, var='a'): """ Return the symplectic group of degree n over R. .. note:: This group is also available via ``groups.matrix.Sp()``. EXAMPLES:: sage: Sp(4,5) Symplectic Group of rank 2 over Finite Field of size 5 sage: Sp(3,GF(7)) Traceback (most recent call last): ... ValueError: the degree n (=3) must be even TESTS:: sage: groups.matrix.Sp(2, 3) Symplectic Group of rank 1 over Finite Field of size 3 """ if n % 2 != 0: raise ValueError, "the degree n (=%s) must be even" % n if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if is_FiniteField(R): return SymplecticGroup_finite_field(n, R) else: return SymplecticGroup_generic(n, R)
def SU(n, F, var='a'): """ Return the special unitary group of degree `n` over `F`. .. note:: This group is also available via ``groups.matrix.SU()``. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field of size 5 sage: SU(3,QQ) Traceback (most recent call last): ... NotImplementedError: special unitary group only implemented over finite fields TESTS:: sage: groups.matrix.SU(2, 3) Special Unitary Group of degree 2 over Finite Field of size 3 """ if isinstance(F, (int, long, Integer)): F = GF(F,var) if is_FiniteField(F): return SpecialUnitaryGroup_finite_field(n, F, var=var) else: raise NotImplementedError, "special unitary group only implemented over finite fields"
def GU(n, F, var='a'): """ Return the general unitary group of degree n over the finite field F. INPUT: - ``n`` - a positive integer - ``F`` - finite field - ``var`` - variable used to represent generator of quadratic extension of F, if needed. .. note:: This group is also available via ``groups.matrix.GU()``. EXAMPLES:: sage: G = GU(3,GF(7)); G General Unitary Group of degree 3 over Finite Field of size 7 sage: G.gens() [ [ a 0 0] [ 0 1 0] [ 0 0 5*a], [6*a 6 1] [ 6 6 0] [ 1 0 0] ] sage: G = GU(2,QQ) Traceback (most recent call last): ... NotImplementedError: general unitary group only implemented over finite fields :: sage: G = GU(3,GF(5), var='beta') sage: G.gens() [ [ beta 0 0] [ 0 1 0] [ 0 0 3*beta], [4*beta 4 1] [ 4 4 0] [ 1 0 0] ] TESTS:: sage: groups.matrix.GU(2, 3) General Unitary Group of degree 2 over Finite Field of size 3 """ if isinstance(F, (int, long, Integer)): F = GF(F, var) if is_FiniteField(F): return GeneralUnitaryGroup_finite_field(n, F, var) else: raise NotImplementedError, "general unitary group only implemented over finite fields"
def GU(n, F, var='a'): """ Return the general unitary group of degree n over the finite field F. INPUT: - ``n`` - a positive integer - ``F`` - finite field - ``var`` - variable used to represent generator of quadratic extension of F, if needed. .. note:: This group is also available via ``groups.matrix.GU()``. EXAMPLES:: sage: G = GU(3,GF(7)); G General Unitary Group of degree 3 over Finite Field of size 7 sage: G.gens() [ [ a 0 0] [ 0 1 0] [ 0 0 5*a], [6*a 6 1] [ 6 6 0] [ 1 0 0] ] sage: G = GU(2,QQ) Traceback (most recent call last): ... NotImplementedError: general unitary group only implemented over finite fields :: sage: G = GU(3,GF(5), var='beta') sage: G.gens() [ [ beta 0 0] [ 0 1 0] [ 0 0 3*beta], [4*beta 4 1] [ 4 4 0] [ 1 0 0] ] TESTS:: sage: groups.matrix.GU(2, 3) General Unitary Group of degree 2 over Finite Field of size 3 """ if isinstance(F, (int, long, Integer)): F = GF(F,var) if is_FiniteField(F): return GeneralUnitaryGroup_finite_field(n, F, var) else: raise NotImplementedError, "general unitary group only implemented over finite fields"
def GL(n, R, var='a'): """ Return the general linear group of degree `n` over the ring `R`. EXAMPLES:: sage: G = GL(6,GF(5)) sage: G.order() 11064475422000000000000000 sage: G.base_ring() Finite Field of size 5 sage: G.category() Category of finite groups sage: TestSuite(G).run() sage: G = GL(6, QQ) sage: G.category() Category of groups sage: TestSuite(G).run() Here is the Cayley graph of (relatively small) finite General Linear Group:: sage: g = GL(2,3) sage: d = g.cayley_graph(); d Digraph on 48 vertices sage: d.show(color_by_label=True, vertex_size=0.03, vertex_labels=False) sage: d.show3d(color_by_label=True) :: sage: F = GF(3); MS = MatrixSpace(F,2,2) sage: gens = [MS([[0,1],[1,0]]),MS([[1,1],[0,1]])] sage: G = MatrixGroup(gens) sage: G.order() 48 sage: G.cardinality() 48 sage: H = GL(2,F) sage: H.order() 48 sage: H == G # Do we really want this equality? False sage: H.as_matrix_group() == G True sage: H.gens() [ [2 0] [0 1], [2 1] [2 0] ] """ if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if is_FiniteField(R): return GeneralLinearGroup_finite_field(n, R) return GeneralLinearGroup_generic(n, R)
def AffineSpace(n, R=None, names='x'): r""" Return affine space of dimension `n` over the ring `R`. EXAMPLES: The dimension and ring can be given in either order:: sage: AffineSpace(3, QQ, 'x') Affine Space of dimension 3 over Rational Field sage: AffineSpace(5, QQ, 'x') Affine Space of dimension 5 over Rational Field sage: A = AffineSpace(2, QQ, names='XY'); A Affine Space of dimension 2 over Rational Field sage: A.coordinate_ring() Multivariate Polynomial Ring in X, Y over Rational Field Use the divide operator for base extension:: sage: AffineSpace(5, names='x')/GF(17) Affine Space of dimension 5 over Finite Field of size 17 The default base ring is `\ZZ`:: sage: AffineSpace(5, names='x') Affine Space of dimension 5 over Integer Ring There is also an affine space associated to each polynomial ring:: sage: R = GF(7)['x,y,z'] sage: A = AffineSpace(R); A Affine Space of dimension 3 over Finite Field of size 7 sage: A.coordinate_ring() is R True """ if is_MPolynomialRing(n) and R is None: R = n A = AffineSpace(R.ngens(), R.base_ring(), R.variable_names()) A._coordinate_ring = R return A if isinstance(R, (int, long, Integer)): n, R = R, n if R is None: R = ZZ # default is the integers if names is None: if n == 0: names = '' else: raise TypeError("You must specify the variables names of the coordinate ring.") if R in _Fields: if is_FiniteField(R): return AffineSpace_finite_field(n, R, names) else: return AffineSpace_field(n, R, names) return AffineSpace_generic(n, R, names)
def SO(n, R, e=0, var="a"): """ Return the special orthogonal group of degree `n` over the ring `R`. INPUT: - ``n`` - the degree - ``R`` - ring - ``e`` - a parameter for orthogonal groups only depending on the invariant form .. note:: This group is also available via ``groups.matrix.SO()``. EXAMPLES:: sage: G = SO(3,GF(5)) sage: G.gens() [ [2 0 0] [0 3 0] [0 0 1], [3 2 3] [0 2 0] [0 3 1], [1 4 4] [4 0 0] [2 0 4] ] sage: G = SO(3,GF(5)) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators: [[[2, 0, 0], [0, 3, 0], [0, 0, 1]], [[3, 2, 3], [0, 2, 0], [0, 3, 1]], [[1, 4, 4], [4, 0, 0], [2, 0, 4]]] TESTS:: sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2, form parameter 1, over the Finite Field of size 3 """ if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if n % 2 != 0 and e != 0: raise ValueError, "must have e = 0 for n even" if n % 2 == 0 and e ** 2 != 1: raise ValueError, "must have e=-1 or e=1 if n is even" if is_FiniteField(R): return SpecialOrthogonalGroup_finite_field(n, R, e) else: return SpecialOrthogonalGroup_generic(n, R, e)
def SL(n, R, var='a'): r""" Return the special linear group of degree `n` over the ring `R`. EXAMPLES:: sage: SL(3,GF(2)) Special Linear Group of degree 3 over Finite Field of size 2 sage: G = SL(15,GF(7)); G Special Linear Group of degree 15 over Finite Field of size 7 sage: G.category() Category of finite groups sage: G.order() 1956712595698146962015219062429586341124018007182049478916067369638713066737882363393519966343657677430907011270206265834819092046250232049187967718149558134226774650845658791865745408000000 sage: len(G.gens()) 2 sage: G = SL(2,ZZ); G Special Linear Group of degree 2 over Integer Ring sage: G.gens() [ [ 0 1] [-1 0], [1 1] [0 1] ] Next we compute generators for `\mathrm{SL}_3(\ZZ)`. :: sage: G = SL(3,ZZ); G Special Linear Group of degree 3 over Integer Ring sage: G.gens() [ [0 1 0] [0 0 1] [1 0 0], [ 0 1 0] [-1 0 0] [ 0 0 1], [1 1 0] [0 1 0] [0 0 1] ] sage: TestSuite(G).run() """ if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if is_FiniteField(R): return SpecialLinearGroup_finite_field(n, R) else: return SpecialLinearGroup_generic(n, R)
def SO(n, R, e=0, var='a'): """ Return the special orthogonal group of degree `n` over the ring `R`. INPUT: - ``n`` - the degree - ``R`` - ring - ``e`` - a parameter for orthogonal groups only depending on the invariant form .. note:: This group is also available via ``groups.matrix.SO()``. EXAMPLES:: sage: G = SO(3,GF(5)) sage: G.gens() [ [2 0 0] [0 3 0] [0 0 1], [3 2 3] [0 2 0] [0 3 1], [1 4 4] [4 0 0] [2 0 4] ] sage: G = SO(3,GF(5)) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators: [[[2, 0, 0], [0, 3, 0], [0, 0, 1]], [[3, 2, 3], [0, 2, 0], [0, 3, 1]], [[1, 4, 4], [4, 0, 0], [2, 0, 4]]] TESTS:: sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2, form parameter 1, over the Finite Field of size 3 """ if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if n%2!=0 and e != 0: raise ValueError, "must have e = 0 for n even" if n%2 == 0 and e**2 != 1: raise ValueError, "must have e=-1 or e=1 if n is even" if is_FiniteField(R): return SpecialOrthogonalGroup_finite_field(n, R, e) else: return SpecialOrthogonalGroup_generic(n, R, e)
def GO( n , R , e=0 ): """ Return the general orthogonal group. EXAMPLES: """ if n%2!=0 and e!=0: raise ValueError, "if e = 0, then n must be even." if n%2 == 0 and e**2!=1: raise ValueError, "must have e=-1 or e=1, if d is even." if isinstance(R, (int, long, Integer)): R = FiniteField(R) if is_FiniteField(R): return GeneralOrthogonalGroup_finite_field(n, R, e) else: return GeneralOrthogonalGroup_generic(n, R, e)
def rational_points(self, F=None): """ Return the list of `F`-rational points on the affine space self, where `F` is a given finite field, or the base ring of self. EXAMPLES:: sage: P = ProjectiveSpace(1, GF(3)) sage: P.rational_points() [(0 : 1), (1 : 1), (2 : 1), (1 : 0)] sage: P.rational_points(GF(3^2, 'b')) [(0 : 1), (b : 1), (b + 1 : 1), (2*b + 1 : 1), (2 : 1), (2*b : 1), (2*b + 2 : 1), (b + 2 : 1), (1 : 1), (1 : 0)] """ if F == None: return [ P for P in self ] elif not is_FiniteField(F): raise TypeError("Second argument (= %s) must be a finite field."%F) return [ P for P in self.base_extend(F) ]
def rational_points(self, F=None): """ Return the list of `F`-rational points on the affine space self, where `F` is a given finite field, or the base ring of self. EXAMPLES:: sage: P = ProjectiveSpace(1, GF(3)) sage: P.rational_points() [(0 : 1), (1 : 1), (2 : 1), (1 : 0)] sage: P.rational_points(GF(3^2, 'b')) [(0 : 1), (b : 1), (b + 1 : 1), (2*b + 1 : 1), (2 : 1), (2*b : 1), (2*b + 2 : 1), (b + 2 : 1), (1 : 1), (1 : 0)] """ if F == None: return [P for P in self] elif not is_FiniteField(F): raise TypeError, "Second argument (= %s) must be a finite field." % F return [P for P in self.base_extend(F)]
def points(self, B=0): r""" Return some or all rational points of an affine scheme. INPUT: - ``B`` -- integer (optional, default: 0). The bound for the height of the coordinates. OUTPUT: - If the base ring is a finite field: all points of the scheme, given by coordinate tuples. - If the base ring is `\QQ` or `\ZZ`: the subset of points whose coordinates have height ``B`` or less. EXAMPLES: The bug reported at #11526 is fixed:: sage: A2 = AffineSpace(ZZ,2) sage: F = GF(3) sage: A2(F).points() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: R = ZZ sage: A.<x,y> = R[] sage: I = A.ideal(x^2-y^2-1) sage: V = AffineSpace(R,2) sage: X = V.subscheme(I) sage: M = X(R) sage: M.points(1) [(-1, 0), (1, 0)] """ R = self.value_ring() if is_RationalField(R) or R == ZZ: if not B > 0: raise TypeError, "A positive bound B (= %s) must be specified."%B from sage.schemes.generic.rational_point import enum_affine_rational_field return enum_affine_rational_field(self,B) elif is_FiniteField(R): from sage.schemes.generic.rational_point import enum_affine_finite_field return enum_affine_finite_field(self) else: raise TypeError, "Unable to enumerate points over %s."%R
def SU(n, F, var='a'): """ Return the special unitary group of degree `n` over `F`. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field of size 5 sage: SU(3,QQ) Traceback (most recent call last): ... NotImplementedError: special unitary group only implemented over finite fields """ if isinstance(F, (int, long, Integer)): F = GF(F,var) if is_FiniteField(F): return SpecialUnitaryGroup_finite_field(n, F, var=var) else: raise NotImplementedError, "special unitary group only implemented over finite fields"
def SU(n, F, var='a'): """ Return the special unitary group of degree `n` over `F`. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field of size 5 sage: SU(3,QQ) Traceback (most recent call last): ... NotImplementedError: special unitary group only implemented over finite fields """ if isinstance(F, (int, long, Integer)): F = GF(F, var) if is_FiniteField(F): return SpecialUnitaryGroup_finite_field(n, F, var=var) else: raise NotImplementedError, "special unitary group only implemented over finite fields"
def Sp(n, R, var='a'): """ Return the symplectic group of degree n over R. EXAMPLES:: sage: Sp(4,5) Symplectic Group of rank 2 over Finite Field of size 5 sage: Sp(3,GF(7)) Traceback (most recent call last): ... ValueError: the degree n (=3) must be even """ if n%2!=0: raise ValueError, "the degree n (=%s) must be even"%n if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if is_FiniteField(R): return SymplecticGroup_finite_field(n, R) else: return SymplecticGroup_generic(n, R)
def normalize_args_e(degree, ring, e): """ Normalize the arguments that relate the choice of quadratic form for special orthogonal groups over finite fields. INPUT: - ``degree`` -- integer. The degree of the affine group, that is, the dimension of the affine space the group is acting on. - ``ring`` -- a ring. The base ring of the affine space. - ``e`` -- integer, one of `+1`, `0`, `-1`. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The integer ``e`` with values required by GAP. TESTS:: sage: from sage.groups.matrix_gps.orthogonal import normalize_args_e sage: normalize_args_e(2, GF(3), +1) 1 sage: normalize_args_e(3, GF(3), 0) 0 sage: normalize_args_e(3, GF(3), +1) 0 sage: normalize_args_e(2, GF(3), 0) Traceback (most recent call last): ... ValueError: must have e=-1 or e=1 for even degree """ if is_FiniteField(ring) and degree%2 == 0: if e not in (-1, +1): raise ValueError('must have e=-1 or e=1 for even degree') else: e = 0 return ZZ(e)
def normalize_args_e(degree, ring, e): """ Normalize the arguments that relate the choice of quadratic form for special orthogonal groups over finite fields. INPUT: - ``degree`` -- integer. The degree of the affine group, that is, the dimension of the affine space the group is acting on. - ``ring`` -- a ring. The base ring of the affine space. - ``e`` -- integer, one of `+1`, `0`, `-1`. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The integer ``e`` with values required by GAP. TESTS:: sage: from sage.groups.matrix_gps.orthogonal import normalize_args_e sage: normalize_args_e(2, GF(3), +1) 1 sage: normalize_args_e(3, GF(3), 0) 0 sage: normalize_args_e(3, GF(3), +1) 0 sage: normalize_args_e(2, GF(3), 0) Traceback (most recent call last): ... ValueError: must have e=-1 or e=1 for even degree """ if is_FiniteField(ring) and degree % 2 == 0: if e not in (-1, +1): raise ValueError('must have e=-1 or e=1 for even degree') else: e = 0 return ZZ(e)
def GO( n , R , e=0 ): """ Return the general orthogonal group. .. note:: This group is also available via ``groups.matrix.GO()``. EXAMPLES: TESTS:: sage: groups.matrix.GO(2, 3, e=-1) General Orthogonal Group of degree 2, form parameter -1, over the Finite Field of size 3 """ if n%2!=0 and e!=0: raise ValueError, "if e = 0, then n must be even." if n%2 == 0 and e**2!=1: raise ValueError, "must have e=-1 or e=1, if d is even." if isinstance(R, (int, long, Integer)): R = FiniteField(R) if is_FiniteField(R): return GeneralOrthogonalGroup_finite_field(n, R, e) else: return GeneralOrthogonalGroup_generic(n, R, e)
def finite_field_sqrt(ring): """ Helper function. INPUT: A ring. OUTPUT: Integer q such that ``ring`` is the finite field with `q^2` elements. EXAMPLES:: sage: from sage.groups.matrix_gps.unitary import finite_field_sqrt sage: finite_field_sqrt(GF(4, 'a')) 2 """ if not is_FiniteField(ring): raise ValueError('not a finite field') q, rem = ring.cardinality().sqrtrem() if rem != 0: raise ValueError('cardinatity not a square') return q
def GO(n, R, e=0): """ Return the general orthogonal group. .. note:: This group is also available via ``groups.matrix.GO()``. EXAMPLES: TESTS:: sage: groups.matrix.GO(2, 3, e=-1) General Orthogonal Group of degree 2, form parameter -1, over the Finite Field of size 3 """ if n % 2 != 0 and e != 0: raise ValueError, "if e = 0, then n must be even." if n % 2 == 0 and e ** 2 != 1: raise ValueError, "must have e=-1 or e=1, if d is even." if isinstance(R, (int, long, Integer)): R = FiniteField(R) if is_FiniteField(R): return GeneralOrthogonalGroup_finite_field(n, R, e) else: return GeneralOrthogonalGroup_generic(n, R, e)
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): r""" There are several ways to construct an elliptic curve: .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. - 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 a1=a2=a3=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): Return an elliptic curve with j-invariant `j`. Warning: this is deprecated. Use ``EllipticCurve_from_j(j)`` or ``EllipticCurve(j=j)`` instead. 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 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 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: is_field(SR) 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 """ 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 rings.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) assert x is not None if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if rings.is_MPolynomial(x) and y is None: f = x if f.degree() != 3: raise ValueError, "Elliptic curves must be defined by a cubic polynomial." if f.degrees() == (3,2): x, y = f.parent().gens() elif f.degree() == (2,3): y, x = f.parent().gens() elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous(): # We'd need a point too... raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." else: raise ValueError, "Defining polynomial must be a cubic polynomial in two variables." try: if f.coefficient(x**3) < 0: f = -f # is there a nicer way to extract the coefficients? a1 = a2 = a3 = a4 = a6 = 0 for coeff, mon in f: if mon == x**3: assert coeff == 1 elif mon == x**2: a2 = coeff elif mon == x: a4 = coeff elif mon == 1: a6 = coeff elif mon == y**2: assert coeff == -1 elif mon == x*y: a1 = -coeff elif mon == y: a3 = -coeff else: assert False return EllipticCurve([a1, a2, a3, a4, a6]) except AssertionError: raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." if rings.is_Ring(x): if rings.is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_FiniteField(x) or (rings.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 rings.is_NumberField(x): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_Field(x): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y) if isinstance(x, unicode): x = str(x) if isinstance(x, str): return ell_rational_field.EllipticCurve_rational_field(x) if rings.is_RingElement(x) and y is None: from sage.misc.misc import deprecation deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.") # Fixed for all characteristics and cases by John Cremona j=x F=j.parent().fraction_field() char=F.characteristic() if char==2: if j==0: return EllipticCurve(F, [ 0, 0, 1, 0, 0 ]) else: return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ]) if char==3: if j==0: return EllipticCurve(F, [ 0, 0, 0, 1, 0 ]) else: return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ]) if j == 0: return EllipticCurve(F, [ 0, 0, 0, 0, 1 ]) if j == 1728: return EllipticCurve(F, [ 0, 0, 0, 1, 0 ]) k=j-1728 return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2]) 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 rings.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 rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_Field(R): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y)
def ProjectiveSpace(n, R=None, names='x'): r""" Return projective space of dimension `n` over the ring `R`. EXAMPLES: The dimension and ring can be given in either order. :: sage: ProjectiveSpace(3, QQ) Projective Space of dimension 3 over Rational Field sage: ProjectiveSpace(5, QQ) Projective Space of dimension 5 over Rational Field sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P Projective Space of dimension 2 over Rational Field sage: P.coordinate_ring() Multivariate Polynomial Ring in X, Y, Z over Rational Field The divide operator does base extension. :: sage: ProjectiveSpace(5)/GF(17) Projective Space of dimension 5 over Finite Field of size 17 The default base ring is `\ZZ`. :: sage: ProjectiveSpace(5) Projective Space of dimension 5 over Integer Ring There is also an projective space associated each polynomial ring. :: sage: R = GF(7)['x,y,z'] sage: P = ProjectiveSpace(R); P Projective Space of dimension 2 over Finite Field of size 7 sage: P.coordinate_ring() Multivariate Polynomial Ring in x, y, z over Finite Field of size 7 sage: P.coordinate_ring() is R True :: sage: ProjectiveSpace(3, Zp(5), 'y') Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20 :: sage: ProjectiveSpace(2,QQ,'x,y,z') Projective Space of dimension 2 over Rational Field :: sage: PS.<x,y>=ProjectiveSpace(1,CC) sage: PS Projective Space of dimension 1 over Complex Field with 53 bits of precision Projective spaces are not cached, i.e., there can be several with the same base ring and dimension (to facilitate gluing constructions). """ if is_MPolynomialRing(n) and R is None: A = ProjectiveSpace(n.ngens()-1, n.base_ring()) A._coordinate_ring = n return A if isinstance(R, (int, long, Integer)): n, R = R, n if R is None: R = ZZ # default is the integers if R in _Fields: if is_FiniteField(R): return ProjectiveSpace_finite_field(n, R, names) if is_RationalField(R): return ProjectiveSpace_rational_field(n, R, names) else: return ProjectiveSpace_field(n, R, names) elif is_CommutativeRing(R): return ProjectiveSpace_ring(n, R, names) else: raise TypeError("R (=%s) must be a commutative ring"%R)
def GO(n, R, e=0, var='a'): """ Return the general orthogonal group. The general orthogonal group `GO(n,R)` consists of all `n\times n` matrices over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are muliple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. In the case of a finite field and if the degree `n` is even, then there are two inequivalent quadratic forms and a third parameter ``e`` must be specified to disambiguate these two possibilities. .. note:: This group is also available via ``groups.matrix.GO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The general orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES: sage: GO( 3, GF(7)) General Orthogonal Group of degree 3 over Finite Field of size 7 sage: GO( 3, GF(7)).order() 672 sage: GO( 3, GF(7)).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] [0 0 1], [0 2 1] ) TESTS:: sage: groups.matrix.GO(2, 3, e=-1) General Orthogonal Group of degree 2 and form parameter -1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'General Orthogonal Group of degree {0} over {1}'.format( degree, ring) ltx = r'\text{{GO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'General Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{GO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'GO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, False, name, ltx)
def EllipticCurve(x=None, y=None, j=None): r""" There are several ways to construct an elliptic curve: .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. - 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 a1=a2=a3=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): Return an elliptic curve with j-invariant `j`. Warning: this is deprecated. Use ``EllipticCurve_from_j(j)`` or ``EllipticCurve(j=j)`` 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 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'> 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'> 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 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'> 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'> 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'> sage: is_field(SR) 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'> """ 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 rings.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) assert x is not None if is_SymbolicEquation(x): x = x.lhs() - x.rhs() if parent(x) is SR: x = x._polynomial_(rings.QQ['x', 'y']) if rings.is_MPolynomial(x) and y is None: f = x if f.degree() != 3: raise ValueError, "Elliptic curves must be defined by a cubic polynomial." if f.degrees() == (3,2): x, y = f.parent().gens() elif f.degree() == (2,3): y, x = f.parent().gens() elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous(): # We'd need a point too... raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." else: raise ValueError, "Defining polynomial must be a cubic polynomial in two variables." try: if f.coefficient(x**3) < 0: f = -f # is there a nicer way to extract the coefficients? a1 = a2 = a3 = a4 = a6 = 0 for coeff, mon in f: if mon == x**3: assert coeff == 1 elif mon == x**2: a2 = coeff elif mon == x: a4 = coeff elif mon == 1: a6 = coeff elif mon == y**2: assert coeff == -1 elif mon == x*y: a1 = -coeff elif mon == y: a3 = -coeff else: assert False return EllipticCurve([a1, a2, a3, a4, a6]) except AssertionError: raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." if rings.is_Ring(x): if rings.is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_FiniteField(x) or (rings.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 rings.is_NumberField(x): return ell_number_field.EllipticCurve_number_field(x, y) elif rings.is_Field(x): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y) if isinstance(x, unicode): x = str(x) if isinstance(x, str): return ell_rational_field.EllipticCurve_rational_field(x) if rings.is_RingElement(x) and y is None: from sage.misc.misc import deprecation deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.") # Fixed for all characteristics and cases by John Cremona j=x F=j.parent().fraction_field() char=F.characteristic() if char==2: if j==0: return EllipticCurve(F, [ 0, 0, 1, 0, 0 ]) else: return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ]) if char==3: if j==0: return EllipticCurve(F, [ 0, 0, 0, 1, 0 ]) else: return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ]) if j == 0: return EllipticCurve(F, [ 0, 0, 0, 0, 1 ]) if j == 1728: return EllipticCurve(F, [ 0, 0, 0, 1, 0 ]) k=j-1728 return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2]) if not isinstance(x,list): 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 rings.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 rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()): return ell_finite_field.EllipticCurve_finite_field(x, y) elif rings.is_Field(R): return ell_field.EllipticCurve_field(x, y) return ell_generic.EllipticCurve_generic(x, y)
def HyperellipticCurve(f,h=None,names=None,PP=None): r""" Returns the hyperelliptic curve `y^2 + h y = f`, for univariate polynomials `h` and `f`. If `h` is not given, then it defaults to 0. INPUT: - ``f`` - univariate polynomial - ``h`` - optional univariate polynomial EXAMPLES: A curve with and without the h term:: sage: R.<x> = QQ[] sage: HyperellipticCurve(x^5 + x + 1) Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x + 1 sage: HyperellipticCurve(x^19 + x + 1, x-2) Hyperelliptic Curve over Rational Field defined by y^2 + (x - 2)*y = x^19 + x + 1 A curve over a non-prime finite field:: sage: k.<a> = GF(9); R.<x> = k[] sage: HyperellipticCurve(x^3 + x - 1, x+a) Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + (x + a)*y = x^3 + x + 2 Here's one where we change the names of the vars in the homogeneous polynomial:: sage: k.<a> = GF(9); R.<x> = k[] sage: HyperellipticCurve(x^3 + x - 1, x+a, names=['X','Y']) Hyperelliptic Curve over Finite Field in a of size 3^2 defined by Y^2 + (X + a)*Y = X^3 + X + 2 """ if not is_Polynomial(f): raise TypeError, "Arguments f (=%s) and h (= %s) must be polynomials"%(f,h) P = f.parent() if h is None: h = P(0) g = (f.degree()-1)%2 try: h = P(h) except TypeError: raise TypeError, \ "Arguments f (=%s) and h (= %s) must be polynomials in the same ring"%(f,h) df = f.degree() dh_2 = 2*h.degree() if dh_2 < df: g = (df-1)//2 elif df < dh_2: g = (dh_2-1)//2 else: a0 = f.leading_coefficient() b0 = h.leading_coefficient() A0 = 4*a0 + b0^2 if A0 != 0: g = (df-1)//2 else: if P(2) == 0: raise TypeError, "Arguments define a curve with finite singularity." f0 = 4*f + h^2 d0 = f0.degree() g = (d0-1)//2 R = P.base_ring() PP = ProjectiveSpace(2, R) if names is None: names = ["x","y"] if is_FiniteField(R): if g == 2: return HyperellipticCurve_g2_finite_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_finite_field(PP, f, h, names=names, genus=g) elif is_RationalField(R): if g == 2: return HyperellipticCurve_g2_rational_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_rational_field(PP, f, h, names=names, genus=g) elif is_pAdicField(R): if g == 2: return HyperellipticCurve_g2_padic_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_padic_field(PP, f, h, names=names, genus=g) else: if g == 2: return HyperellipticCurve_g2_generic(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_generic(PP, f, h, names=names, genus=g)
def GO(n, R, e=0, var='a'): """ Return the general orthogonal group. The general orthogonal group `GO(n,R)` consists of all `n\times n` matrices over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are muliple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. In the case of a finite field and if the degree `n` is even, then there are two inequivalent quadratic forms and a third parameter ``e`` must be specified to disambiguate these two possibilities. .. note:: This group is also available via ``groups.matrix.GO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The general orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES: sage: GO( 3, GF(7)) General Orthogonal Group of degree 3 over Finite Field of size 7 sage: GO( 3, GF(7)).order() 672 sage: GO( 3, GF(7)).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] [0 0 1], [0 2 1] ) TESTS:: sage: groups.matrix.GO(2, 3, e=-1) General Orthogonal Group of degree 2 and form parameter -1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'General Orthogonal Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{GO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'General Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{GO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'GO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, False, name, ltx)
def GL(n, R, var='a'): """ Return the general linear group of degree `n` over the ring `R`. .. note:: This group is also available via ``groups.matrix.GL()``. EXAMPLES:: sage: G = GL(6,GF(5)) sage: G.order() 11064475422000000000000000 sage: G.base_ring() Finite Field of size 5 sage: G.category() Category of finite groups sage: TestSuite(G).run() sage: G = GL(6, QQ) sage: G.category() Category of groups sage: TestSuite(G).run() Here is the Cayley graph of (relatively small) finite General Linear Group:: sage: g = GL(2,3) sage: d = g.cayley_graph(); d Digraph on 48 vertices sage: d.show(color_by_label=True, vertex_size=0.03, vertex_labels=False) sage: d.show3d(color_by_label=True) :: sage: F = GF(3); MS = MatrixSpace(F,2,2) sage: gens = [MS([[0,1],[1,0]]),MS([[1,1],[0,1]])] sage: G = MatrixGroup(gens) sage: G.order() 48 sage: G.cardinality() 48 sage: H = GL(2,F) sage: H.order() 48 sage: H == G # Do we really want this equality? False sage: H.as_matrix_group() == G True sage: H.gens() [ [2 0] [0 1], [2 1] [2 0] ] TESTS:: sage: groups.matrix.GL(2, 3) General Linear Group of degree 2 over Finite Field of size 3 """ if isinstance(R, (int, long, Integer)): R = FiniteField(R, var) if is_FiniteField(R): return GeneralLinearGroup_finite_field(n, R) return GeneralLinearGroup_generic(n, R)
def lfsr_sequence(key, fill, n): r""" This function creates an lfsr sequence. INPUT: - ``key`` - a list of finite field elements, [c_0,c_1,...,c_k]. - ``fill`` - the list of the initial terms of the lfsr sequence, [x_0,x_1,...,x_k]. - ``n`` - number of terms of the sequence that the function returns. OUTPUT: The lfsr sequence defined by `x_{n+1} = c_kx_n+...+c_0x_{n-k}`, for `n \leq k`. EXAMPLES:: sage: F = GF(2); l = F(1); o = F(0) sage: F = GF(2); S = LaurentSeriesRing(F,'x'); x = S.gen() sage: fill = [l,l,o,l]; key = [1,o,o,l]; n = 20 sage: L = lfsr_sequence(key,fill,20); L [1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0] sage: g = berlekamp_massey(L); g x^4 + x^3 + 1 sage: (1)/(g.reverse()+O(x^20)) 1 + x + x^2 + x^3 + x^5 + x^7 + x^8 + x^11 + x^15 + x^16 + x^17 + x^18 + O(x^20) sage: (1+x^2)/(g.reverse()+O(x^20)) 1 + x + x^4 + x^8 + x^9 + x^10 + x^11 + x^13 + x^15 + x^16 + x^19 + O(x^20) sage: (1+x^2+x^3)/(g.reverse()+O(x^20)) 1 + x + x^3 + x^5 + x^6 + x^9 + x^13 + x^14 + x^15 + x^16 + x^18 + O(x^20) sage: fill = [l,l,o,l]; key = [l,o,o,o]; n = 20 sage: L = lfsr_sequence(key,fill,20); L [1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1] sage: g = berlekamp_massey(L); g x^4 + 1 sage: (1+x)/(g.reverse()+O(x^20)) 1 + x + x^4 + x^5 + x^8 + x^9 + x^12 + x^13 + x^16 + x^17 + O(x^20) sage: (1+x+x^3)/(g.reverse()+O(x^20)) 1 + x + x^3 + x^4 + x^5 + x^7 + x^8 + x^9 + x^11 + x^12 + x^13 + x^15 + x^16 + x^17 + x^19 + O(x^20) AUTHORS: - Timothy Brock (2005-11): with code modified from Python Cookbook, http://aspn.activestate.com/ASPN/Python/Cookbook/ """ if not isinstance(key, list): raise TypeError, "key must be a list" key = Sequence(key) F = key.universe() if not is_FiniteField(F): raise TypeError, "universe of sequence must be a finite field" s = fill k = len(fill) L = [] for i in range(n): s0 = copy.copy(s) L.append(s[0]) s = s[1:k] s.append(sum([key[i]*s0[i] for i in range(k)])) return L
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 (is_IntegralDomain(base_field) or base_field == None): 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 == 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 is_IntegralDomain(P): 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 == 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 == None: base_field = F.base_ring() if not is_IntegralDomain(base_field): raise ValueError, "Base field (=%s) must be a field" % base_field base_field = base_field.fraction_field() if names == 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) return ProjectiveConic_field(P2, F) raise TypeError, "Number of variables of F (=%s) must be 2 or 3" % F
def lfsr_sequence(key, fill, n): r""" This function creates an lfsr sequence. INPUT: - ``key`` - a list of finite field elements, [c_0,c_1,...,c_k]. - ``fill`` - the list of the initial terms of the lfsr sequence, [x_0,x_1,...,x_k]. - ``n`` - number of terms of the sequence that the function returns. OUTPUT: The lfsr sequence defined by `x_{n+1} = c_kx_n+...+c_0x_{n-k}`, for `n \leq k`. EXAMPLES:: sage: F = GF(2); l = F(1); o = F(0) sage: F = GF(2); S = LaurentSeriesRing(F,'x'); x = S.gen() sage: fill = [l,l,o,l]; key = [1,o,o,l]; n = 20 sage: L = lfsr_sequence(key,fill,20); L [1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0] sage: g = berlekamp_massey(L); g x^4 + x^3 + 1 sage: (1)/(g.reverse()+O(x^20)) 1 + x + x^2 + x^3 + x^5 + x^7 + x^8 + x^11 + x^15 + x^16 + x^17 + x^18 + O(x^20) sage: (1+x^2)/(g.reverse()+O(x^20)) 1 + x + x^4 + x^8 + x^9 + x^10 + x^11 + x^13 + x^15 + x^16 + x^19 + O(x^20) sage: (1+x^2+x^3)/(g.reverse()+O(x^20)) 1 + x + x^3 + x^5 + x^6 + x^9 + x^13 + x^14 + x^15 + x^16 + x^18 + O(x^20) sage: fill = [l,l,o,l]; key = [l,o,o,o]; n = 20 sage: L = lfsr_sequence(key,fill,20); L [1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1] sage: g = berlekamp_massey(L); g x^4 + 1 sage: (1+x)/(g.reverse()+O(x^20)) 1 + x + x^4 + x^5 + x^8 + x^9 + x^12 + x^13 + x^16 + x^17 + O(x^20) sage: (1+x+x^3)/(g.reverse()+O(x^20)) 1 + x + x^3 + x^4 + x^5 + x^7 + x^8 + x^9 + x^11 + x^12 + x^13 + x^15 + x^16 + x^17 + x^19 + O(x^20) AUTHORS: - Timothy Brock (2005-11): with code modified from Python Cookbook, http://aspn.activestate.com/ASPN/Python/Cookbook/ """ if not isinstance(key, list): raise TypeError, "key must be a list" key = Sequence(key) F = key.universe() if not is_FiniteField(F): raise TypeError, "universe of sequence must be a finite field" s = fill k = len(fill) L = [] for i in range(n): s0 = copy.copy(s) L.append(s[0]) s = s[1:k] s.append(sum([key[i] * s0[i] for i in range(k)])) return L
def GU(n, R, var='a'): r""" Return the general unitary group. The general unitary group `GU( d, R )` consists of all `d \times d` matrices that preserve a nondegenerate sequilinear form over the ring `R`. .. note:: For a finite field the matrices that preserve a sesquilinear form over `F_q` live over `F_{q^2}`. So ``GU(n,q)`` for integer ``q`` constructs the matrix group over the base ring ``GF(q^2)``. .. note:: This group is also available via ``groups.matrix.GU()``. INPUT: - ``n`` -- a positive integer. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``var`` -- variable used to represent generator of the finite field, if needed. OUTPUT: Return the general unitary group. EXAMPLES:: sage: G = GU(3, 7); G General Unitary Group of degree 3 over Finite Field in a of size 7^2 sage: G.gens() ( [ a 0 0] [6*a 6 1] [ 0 1 0] [ 6 6 0] [ 0 0 5*a], [ 1 0 0] ) sage: GU(2,QQ) General Unitary Group of degree 2 over Rational Field sage: G = GU(3, 5, var='beta') sage: G.base_ring() Finite Field in beta of size 5^2 sage: G.gens() ( [ beta 0 0] [4*beta 4 1] [ 0 1 0] [ 4 4 0] [ 0 0 3*beta], [ 1 0 0] ) TESTS:: sage: groups.matrix.GU(2, 3) General Unitary Group of degree 2 over Finite Field in a of size 3^2 """ degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q ** 2, name=var) name = 'General Unitary Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{GU}}_{{{0}}}({1})'.format(degree, latex(ring)) if is_FiniteField(ring): cmd = 'GU({0}, {1})'.format(degree, q) return UnitaryMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, False, name, ltx)
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 rings.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 rings.is_MPolynomial(x): if y is None: return EllipticCurve_from_Weierstrass_polynomial(x) else: return EllipticCurve_from_cubic(x, y, morphism=False) if rings.is_Ring(x): if rings.is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_FiniteField(x) or (rings.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 rings.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 rings.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 rings.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 rings.is_FiniteField(R) or (rings.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 ProjectiveSpace(n, R=None, names='x'): r""" Return projective space of dimension `n` over the ring `R`. EXAMPLES: The dimension and ring can be given in either order. :: sage: ProjectiveSpace(3, QQ) Projective Space of dimension 3 over Rational Field sage: ProjectiveSpace(5, QQ) Projective Space of dimension 5 over Rational Field sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P Projective Space of dimension 2 over Rational Field sage: P.coordinate_ring() Multivariate Polynomial Ring in X, Y, Z over Rational Field The divide operator does base extension. :: sage: ProjectiveSpace(5)/GF(17) Projective Space of dimension 5 over Finite Field of size 17 The default base ring is `\ZZ`. :: sage: ProjectiveSpace(5) Projective Space of dimension 5 over Integer Ring There is also an projective space associated each polynomial ring. :: sage: R = GF(7)['x,y,z'] sage: P = ProjectiveSpace(R); P Projective Space of dimension 2 over Finite Field of size 7 sage: P.coordinate_ring() Multivariate Polynomial Ring in x, y, z over Finite Field of size 7 sage: P.coordinate_ring() is R True :: sage: ProjectiveSpace(3, Zp(5), 'y') Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20 :: sage: ProjectiveSpace(2,QQ,'x,y,z') Projective Space of dimension 2 over Rational Field :: sage: PS.<x,y>=ProjectiveSpace(1,CC) sage: PS Projective Space of dimension 1 over Complex Field with 53 bits of precision Projective spaces are not cached, i.e., there can be several with the same base ring and dimension (to facilitate gluing constructions). """ if is_MPolynomialRing(n) and R is None: A = ProjectiveSpace(n.ngens() - 1, n.base_ring()) A._coordinate_ring = n return A if isinstance(R, (int, long, Integer)): n, R = R, n if R is None: R = ZZ # default is the integers if R in _Fields: if is_FiniteField(R): return ProjectiveSpace_finite_field(n, R, names) if is_RationalField(R): return ProjectiveSpace_rational_field(n, R, names) else: return ProjectiveSpace_field(n, R, names) elif is_CommutativeRing(R): return ProjectiveSpace_ring(n, R, names) else: raise TypeError, "R (=%s) must be a commutative ring" % R
def SO(n, R, e=None, var='a'): """ Return the special orthogonal group. The special orthogonal group `GO(n,R)` consists of all `n\times n` matrices with determint one over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are muliple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. .. note:: This group is also available via ``groups.matrix.SO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The special orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES:: sage: G = SO(3,GF(5)) sage: G Special Orthogonal Group of degree 3 over Finite Field of size 5 sage: G = SO(3,GF(5)) sage: G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) sage: G = SO(3,GF(5)) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) TESTS:: sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2 and form parameter 1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'Special Orthogonal Group of degree {0} over {1}'.format( degree, ring) ltx = r'\text{{SO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'Special Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{SO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'SO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, True, name, ltx)
def HyperellipticCurve(f, h=None, names=None, PP=None, check_squarefree=True): r""" Returns the hyperelliptic curve `y^2 + h y = f`, for univariate polynomials `h` and `f`. If `h` is not given, then it defaults to 0. INPUT: - ``f`` - univariate polynomial - ``h`` - optional univariate polynomial - ``names`` (default: ``["x","y"]``) - names for the coordinate functions - ``check_squarefree`` (default: ``True``) - test if the input defines a hyperelliptic curve when f is homogenized to degree `2g+2` and h to degree `g+1` for some g. .. WARNING:: When setting ``check_squarefree=False`` or using a base ring that is not a field, the output curves are not to be trusted. For example, the output of ``is_singular`` is always ``False``, without this being properly tested in that case. .. NOTE:: The words "hyperelliptic curve" are normally only used for curves of genus at least two, but this class allows more general smooth double covers of the projective line (conics and elliptic curves), even though the class is not meant for those and some outputs may be incorrect. EXAMPLES: Basic examples:: sage: R.<x> = QQ[] sage: HyperellipticCurve(x^5 + x + 1) Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x + 1 sage: HyperellipticCurve(x^19 + x + 1, x-2) Hyperelliptic Curve over Rational Field defined by y^2 + (x - 2)*y = x^19 + x + 1 sage: k.<a> = GF(9); R.<x> = k[] sage: HyperellipticCurve(x^3 + x - 1, x+a) Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + (x + a)*y = x^3 + x + 2 Characteristic two:: sage: P.<x> = GF(8,'a')[] sage: HyperellipticCurve(x^7+1, x) Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + x*y = x^7 + 1 sage: HyperellipticCurve(x^8+x^7+1, x^4+1) Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + (x^4 + 1)*y = x^8 + x^7 + 1 sage: HyperellipticCurve(x^8+1, x) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: highly singular at infinity. sage: HyperellipticCurve(x^8+x^7+1, x^4) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. sage: F.<t> = PowerSeriesRing(FiniteField(2)) sage: P.<x> = PolynomialRing(FractionField(F)) sage: HyperellipticCurve(x^5+t, x) Hyperelliptic Curve over Laurent Series Ring in t over Finite Field of size 2 defined by y^2 + x*y = x^5 + t We can change the names of the variables in the output:: sage: k.<a> = GF(9); R.<x> = k[] sage: HyperellipticCurve(x^3 + x - 1, x+a, names=['X','Y']) Hyperelliptic Curve over Finite Field in a of size 3^2 defined by Y^2 + (X + a)*Y = X^3 + X + 2 This class also allows curves of genus zero or one, which are strictly speaking not hyperelliptic:: sage: P.<x> = QQ[] sage: HyperellipticCurve(x^2+1) Hyperelliptic Curve over Rational Field defined by y^2 = x^2 + 1 sage: HyperellipticCurve(x^4-1) Hyperelliptic Curve over Rational Field defined by y^2 = x^4 - 1 sage: HyperellipticCurve(x^3+2*x+2) Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + 2*x + 2 Double roots:: sage: P.<x> = GF(7)[] sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1)) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1), check_squarefree=False) Hyperelliptic Curve over Finite Field of size 7 defined by y^2 = x^12 + 5*x^10 + 4*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 + 6*x^2 + 4*x + 3 The input for a (smooth) hyperelliptic curve of genus `g` should not contain polynomials of degree greater than `2g+2`. In the following example, the hyperelliptic curve has genus 2 and there exists a model `y^2 = F` of degree 6, so the model `y^2 + yh = f` of degree 200 is not allowed.:: sage: P.<x> = QQ[] sage: h = x^100 sage: F = x^6+1 sage: f = F-h^2/4 sage: HyperellipticCurve(f, h) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: highly singular at infinity. sage: HyperellipticCurve(F) Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 1 An example with a singularity over an inseparable extension of the base field:: sage: F.<t> = GF(5)[] sage: P.<x> = F[] sage: HyperellipticCurve(x^5+t) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. Input with integer coefficients creates objects with the integers as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`). In other words, it is checked that the discriminant is non-zero, but it is not checked whether the discriminant is a unit in `\ZZ^*`.:: sage: P.<x> = ZZ[] sage: HyperellipticCurve(3*x^7+6*x+6) Hyperelliptic Curve over Integer Ring defined by y^2 = 3*x^7 + 6*x + 6 """ if (not is_Polynomial(f)) or f == 0: raise TypeError, "Arguments f (=%s) and h (= %s) must be polynomials " \ "and f must be non-zero" % (f,h) P = f.parent() if h is None: h = P(0) try: h = P(h) except TypeError: raise TypeError, \ "Arguments f (=%s) and h (= %s) must be polynomials in the same ring"%(f,h) df = f.degree() dh_2 = 2 * h.degree() if dh_2 < df: g = (df - 1) // 2 else: g = (dh_2 - 1) // 2 if check_squarefree: # Assuming we are working over a field, this checks that after # resolving the singularity at infinity, we get a smooth double cover # of P^1. if P(2) == 0: # characteristic 2 if h == 0: raise ValueError, \ "In characteristic 2, argument h (= %s) must be non-zero."%h if h[g + 1] == 0 and f[2 * g + 1]**2 == f[2 * g + 2] * h[g]**2: raise ValueError, "Not a hyperelliptic curve: " \ "highly singular at infinity." should_be_coprime = [h, f * h.derivative()**2 + f.derivative()**2] else: # characteristic not 2 F = f + h**2 / 4 if not F.degree() in [2 * g + 1, 2 * g + 2]: raise ValueError, "Not a hyperelliptic curve: " \ "highly singular at infinity." should_be_coprime = [F, F.derivative()] try: smooth = should_be_coprime[0].gcd( should_be_coprime[1]).degree() == 0 except (AttributeError, NotImplementedError, TypeError): try: smooth = should_be_coprime[0].resultant( should_be_coprime[1]) != 0 except (AttributeError, NotImplementedError, TypeError): raise NotImplementedError, "Cannot determine whether " \ "polynomials %s have a common root. Use " \ "check_squarefree=False to skip this check." % \ should_be_coprime if not smooth: raise ValueError, "Not a hyperelliptic curve: " \ "singularity in the provided affine patch." R = P.base_ring() PP = ProjectiveSpace(2, R) if names is None: names = ["x", "y"] if is_FiniteField(R): if g == 2: return HyperellipticCurve_g2_finite_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_finite_field(PP, f, h, names=names, genus=g) elif is_RationalField(R): if g == 2: return HyperellipticCurve_g2_rational_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_rational_field(PP, f, h, names=names, genus=g) elif is_pAdicField(R): if g == 2: return HyperellipticCurve_g2_padic_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_padic_field(PP, f, h, names=names, genus=g) else: if g == 2: return HyperellipticCurve_g2_generic(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_generic(PP, f, h, names=names, genus=g)
def EllipticCurve(x=None, y=None, j=None, minimal_twist=True): r""" There are several ways to construct an elliptic curve: .. math:: y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6. - 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 a1=a2=a3=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`. 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 rings.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 rings.is_MPolynomial(x) and y is None: f = x if f.degree() != 3: raise ValueError, "Elliptic curves must be defined by a cubic polynomial." if f.degrees() == (3,2): x, y = f.parent().gens() elif f.degree() == (2,3): y, x = f.parent().gens() elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous(): # We'd need a point too... raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." else: raise ValueError, "Defining polynomial must be a cubic polynomial in two variables." try: if f.coefficient(x**3) < 0: f = -f # is there a nicer way to extract the coefficients? a1 = a2 = a3 = a4 = a6 = 0 for coeff, mon in f: if mon == x**3: assert coeff == 1 elif mon == x**2: a2 = coeff elif mon == x: a4 = coeff elif mon == 1: a6 = coeff elif mon == y**2: assert coeff == -1 elif mon == x*y: a1 = -coeff elif mon == y: a3 = -coeff else: assert False return EllipticCurve([a1, a2, a3, a4, a6]) except AssertionError: raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented." if rings.is_Ring(x): if rings.is_RationalField(x): return ell_rational_field.EllipticCurve_rational_field(x, y) elif rings.is_FiniteField(x) or (rings.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 rings.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, str): return ell_rational_field.EllipticCurve_rational_field(x) if rings.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 rings.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 rings.is_FiniteField(R) or (rings.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 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 HyperellipticCurve(f, h=None, names=None, PP=None, check_squarefree=True): r""" Returns the hyperelliptic curve `y^2 + h y = f`, for univariate polynomials `h` and `f`. If `h` is not given, then it defaults to 0. INPUT: - ``f`` - univariate polynomial - ``h`` - optional univariate polynomial - ``names`` (default: ``["x","y"]``) - names for the coordinate functions - ``check_squarefree`` (default: ``True``) - test if the input defines a hyperelliptic curve when f is homogenized to degree `2g+2` and h to degree `g+1` for some g. .. WARNING:: When setting ``check_squarefree=False`` or using a base ring that is not a field, the output curves are not to be trusted. For example, the output of ``is_singular`` is always ``False``, without this being properly tested in that case. .. NOTE:: The words "hyperelliptic curve" are normally only used for curves of genus at least two, but this class allows more general smooth double covers of the projective line (conics and elliptic curves), even though the class is not meant for those and some outputs may be incorrect. EXAMPLES: Basic examples:: sage: R.<x> = QQ[] sage: HyperellipticCurve(x^5 + x + 1) Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x + 1 sage: HyperellipticCurve(x^19 + x + 1, x-2) Hyperelliptic Curve over Rational Field defined by y^2 + (x - 2)*y = x^19 + x + 1 sage: k.<a> = GF(9); R.<x> = k[] sage: HyperellipticCurve(x^3 + x - 1, x+a) Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + (x + a)*y = x^3 + x + 2 Characteristic two:: sage: P.<x> = GF(8,'a')[] sage: HyperellipticCurve(x^7+1, x) Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + x*y = x^7 + 1 sage: HyperellipticCurve(x^8+x^7+1, x^4+1) Hyperelliptic Curve over Finite Field in a of size 2^3 defined by y^2 + (x^4 + 1)*y = x^8 + x^7 + 1 sage: HyperellipticCurve(x^8+1, x) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: highly singular at infinity. sage: HyperellipticCurve(x^8+x^7+1, x^4) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. sage: F.<t> = PowerSeriesRing(FiniteField(2)) sage: P.<x> = PolynomialRing(FractionField(F)) sage: HyperellipticCurve(x^5+t, x) Hyperelliptic Curve over Laurent Series Ring in t over Finite Field of size 2 defined by y^2 + x*y = x^5 + t We can change the names of the variables in the output:: sage: k.<a> = GF(9); R.<x> = k[] sage: HyperellipticCurve(x^3 + x - 1, x+a, names=['X','Y']) Hyperelliptic Curve over Finite Field in a of size 3^2 defined by Y^2 + (X + a)*Y = X^3 + X + 2 This class also allows curves of genus zero or one, which are strictly speaking not hyperelliptic:: sage: P.<x> = QQ[] sage: HyperellipticCurve(x^2+1) Hyperelliptic Curve over Rational Field defined by y^2 = x^2 + 1 sage: HyperellipticCurve(x^4-1) Hyperelliptic Curve over Rational Field defined by y^2 = x^4 - 1 sage: HyperellipticCurve(x^3+2*x+2) Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + 2*x + 2 Double roots:: sage: P.<x> = GF(7)[] sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1)) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1), check_squarefree=False) Hyperelliptic Curve over Finite Field of size 7 defined by y^2 = x^12 + 5*x^10 + 4*x^9 + x^8 + 3*x^7 + 3*x^6 + 2*x^4 + 3*x^3 + 6*x^2 + 4*x + 3 The input for a (smooth) hyperelliptic curve of genus `g` should not contain polynomials of degree greater than `2g+2`. In the following example, the hyperelliptic curve has genus 2 and there exists a model `y^2 = F` of degree 6, so the model `y^2 + yh = f` of degree 200 is not allowed.:: sage: P.<x> = QQ[] sage: h = x^100 sage: F = x^6+1 sage: f = F-h^2/4 sage: HyperellipticCurve(f, h) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: highly singular at infinity. sage: HyperellipticCurve(F) Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 1 An example with a singularity over an inseparable extension of the base field:: sage: F.<t> = GF(5)[] sage: P.<x> = F[] sage: HyperellipticCurve(x^5+t) Traceback (most recent call last): ... ValueError: Not a hyperelliptic curve: singularity in the provided affine patch. Input with integer coefficients creates objects with the integers as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`). In other words, it is checked that the discriminant is non-zero, but it is not checked whether the discriminant is a unit in `\ZZ^*`.:: sage: P.<x> = ZZ[] sage: HyperellipticCurve(3*x^7+6*x+6) Hyperelliptic Curve over Integer Ring defined by y^2 = 3*x^7 + 6*x + 6 """ if (not is_Polynomial(f)) or f == 0: raise TypeError, "Arguments f (=%s) and h (= %s) must be polynomials " \ "and f must be non-zero" % (f,h) P = f.parent() if h is None: h = P(0) try: h = P(h) except TypeError: raise TypeError, \ "Arguments f (=%s) and h (= %s) must be polynomials in the same ring"%(f,h) df = f.degree() dh_2 = 2*h.degree() if dh_2 < df: g = (df-1)//2 else: g = (dh_2-1)//2 if check_squarefree: # Assuming we are working over a field, this checks that after # resolving the singularity at infinity, we get a smooth double cover # of P^1. if P(2) == 0: # characteristic 2 if h == 0: raise ValueError, \ "In characteristic 2, argument h (= %s) must be non-zero."%h if h[g+1] == 0 and f[2*g+1]**2 == f[2*g+2]*h[g]**2: raise ValueError, "Not a hyperelliptic curve: " \ "highly singular at infinity." should_be_coprime = [h, f*h.derivative()**2+f.derivative()**2] else: # characteristic not 2 F = f + h**2/4 if not F.degree() in [2*g+1, 2*g+2]: raise ValueError, "Not a hyperelliptic curve: " \ "highly singular at infinity." should_be_coprime = [F, F.derivative()] try: smooth = should_be_coprime[0].gcd(should_be_coprime[1]).degree()==0 except (AttributeError, NotImplementedError, TypeError): try: smooth = should_be_coprime[0].resultant(should_be_coprime[1])!=0 except (AttributeError, NotImplementedError, TypeError): raise NotImplementedError, "Cannot determine whether " \ "polynomials %s have a common root. Use " \ "check_squarefree=False to skip this check." % \ should_be_coprime if not smooth: raise ValueError, "Not a hyperelliptic curve: " \ "singularity in the provided affine patch." R = P.base_ring() PP = ProjectiveSpace(2, R) if names is None: names = ["x","y"] if is_FiniteField(R): if g == 2: return HyperellipticCurve_g2_finite_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_finite_field(PP, f, h, names=names, genus=g) elif is_RationalField(R): if g == 2: return HyperellipticCurve_g2_rational_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_rational_field(PP, f, h, names=names, genus=g) elif is_pAdicField(R): if g == 2: return HyperellipticCurve_g2_padic_field(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_padic_field(PP, f, h, names=names, genus=g) else: if g == 2: return HyperellipticCurve_g2_generic(PP, f, h, names=names, genus=g) else: return HyperellipticCurve_generic(PP, f, h, names=names, genus=g)
def SO(n, R, e=None, var='a'): """ Return the special orthogonal group. The special orthogonal group `GO(n,R)` consists of all `n\times n` matrices with determint one over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are muliple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. .. note:: This group is also available via ``groups.matrix.SO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The special orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES:: sage: G = SO(3,GF(5)) sage: G Special Orthogonal Group of degree 3 over Finite Field of size 5 sage: G = SO(3,GF(5)) sage: G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) sage: G = SO(3,GF(5)) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) TESTS:: sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2 and form parameter 1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'Special Orthogonal Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{SO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'Special Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{SO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'SO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, True, name, ltx)