source: sage/schemes/generic/divisor.py @ 2147:ddb5b53a2e2c

Revision 2147:ddb5b53a2e2c, 8.4 KB checked in by William Stein <wstein@…>, 6 years ago (diff)

Implemented more general formal sums.

Line 
1"""
2Divisors on schemes
3
4AUTHORS:
5   -- William Stein
6   -- David Kohel
7   -- David Joyner
8
9EXAMPLES:
10    sage: x,y,z = ProjectiveSpace(2, GF(5), names='x,y,z').gens()
11    sage: C = Curve(y^2*z^7 - x^9 - x*z^8)
12    sage: pts = C.rational_points(); pts
13    [(0 : 0 : 1), (0 : 1 : 0), (2 : 2 : 1), (2 : 3 : 1), (3 : 1 : 1), (3 : 4 : 1)]
14    sage: D1 = C.divisor(pts[0])*3
15    sage: D2 = C.divisor(pts[1])
16    sage: D3 = 10*C.divisor(pts[5])
17    sage: D1.parent() is D2.parent()
18    True
19    sage: D = D1 - D2 + D3; D
20    10*(z + y, 2*z + x) + 3*(y, x) - (z, x)
21    sage: D[1][0]
22    3
23    sage: D[1][1]
24    Ideal (y, x) of Polynomial Ring in x, y, z over Finite Field of size 5
25    sage: C.divisor([(3, pts[0]), (-1, pts[1]), (10,pts[5])])
26    10*(z + y, 2*z + x) + 3*(y, x) - (z, x)
27"""
28#*******************************************************************************
29#  Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu.au>
30#  Copyright (C) 2005 William Stein
31#  Distributed under the terms of the GNU General Public License (GPL)
32#                  http://www.gnu.org/licenses/
33#*******************************************************************************
34
35import sage.misc.misc #as repr_lincomb
36
37from sage.structure.formal_sum import FormalSum
38
39from sage.rings.all import ZZ
40
41from projective_space import is_ProjectiveSpace
42
43from affine_space import is_AffineSpace
44
45from morphism import is_SchemeMorphism
46
47import divisor_group
48
49from sage.misc.search import search
50
51
52def CurvePointToIdeal(C,P):
53    A = C.ambient_space()
54    R = A.coordinate_ring()
55    n = A.ngens()
56    x = A.gens()
57    polys = [ ]
58    m = n-1
59    while m > 0 and P[m] == 0:
60        m += -1
61    if is_ProjectiveSpace(A):
62        a_m = P[m]
63        x_m = x[m]
64        for i in range(m):
65            ai = P[i]
66            if ai == 0: 
67                polys.append(x[i])
68            else:
69                polys.append(a_m*x[i]-ai*x_m)
70    elif is_AffineSpace(A):
71        for i in range(m+1):
72            ai = P[i]
73            if ai == 0: 
74                polys.append(x[i])
75            else:
76                polys.append(x[i]-ai)
77    for i in range(m+1,n):
78        polys.append(x[i])
79    return R.ideal(polys)
80
81def is_Divisor(Div):
82    return isinstance(Div, Divisor_generic)
83
84def is_DivisorGroup(Div):
85    return isinstance(Div, DivisorGroup_generic)
86
87class Divisor_generic(FormalSum):
88    def __init__(self, v, check=True, reduce=True, parent=None):
89        FormalSum.__init__(self, v, parent, check, reduce)
90       
91    def scheme(self):
92        """
93        Return the scheme that this divisor is on.
94
95        EXAMPLES:
96            sage: A.<x, y> = AffineSpace(2, GF(5))
97            sage: C = Curve(y^2 - x^9 - x)
98            sage: pts = C.rational_points(); pts
99            [(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
100            sage: D = C.divisor(pts[0])*3 - C.divisor(pts[1]); D
101            -(3 + y, 3 + x) + 3*(y, x)
102            sage: D.scheme()
103            Affine Curve over Finite Field of size 5 defined by y^2 + 4*x + 4*x^9
104        """
105        return self.parent().scheme()
106
107class Divisor_curve(Divisor_generic):
108    r"""
109    For any curve $C$, use \code{C.divisor(v)} to construct a divisor
110    on $C$.  Here $v$ can be either
111    \begin{itemize}
112       \item a rational point on $C$
113       \item a list of rational points
114       \item a list of 2-tuples $(c,P)$, where $c$ is
115             an integer and $P$ is a rational point.
116    \end{itemize}
117
118    TODO: Divisors shouldn't be restricted to rational points.  The
119    problem is that the divisor group is the formal sum of the group
120    of points on the curve, and there's no implemented notion of point
121    on $E/K$ that has coordinates in $L$.   This is what should
122    be implemented, by adding an appropriate class to
123    \code{schemes/generic/morphism.py}.
124
125    EXAMPLES:
126        sage: E = EllipticCurve([0, 0, 1, -1, 0])
127        sage: P = E(0,0)
128        sage: 10*P
129        (161/16 : -2065/64 : 1)
130        sage: D = E.divisor(P)
131        sage: D
132        (y, x)
133        sage: 10*D
134        10*(y, x)
135        sage: E.divisor([P, P])
136        2*(y, x)
137        sage: E.divisor([(3,P), (-4,5*P)])
138        -4*(5/8*z + y, -1/4*z + x) + 3*(y, x)
139    """
140    def __init__(self, v, check=True, reduce=True, parent=None):
141        """
142        INPUT:
143            v -- a list of pairs (c, P), where c is an integer
144                 and P is a point on a curve.  The P's must
145                 all lie on the same curve.
146                 
147        To create the 0 divisor use [(0, P)], so as to give
148        the curve.
149       
150        TODO: Include an extension field in the definition of the
151        divisor group.
152        """
153        if not isinstance(v, (list, tuple)):
154            v = [(1,v)]
155
156        if parent is None:
157            if len(v) > 0:
158                t = v[0]
159                if isinstance(t, tuple) and len(t) == 2:
160                    try:
161                        C = t[1].scheme()
162                    except (TypeError, AttributeError):
163                        raise TypeError, \
164                              "Argument v (= %s) must consist of multiplicities and points on a scheme."
165                else:
166                    try:
167                        C = t.scheme()
168                    except TypeError:
169                        raise TypeError, \
170                              "Argument v (= %s) must consist of multiplicities and points on a scheme."
171                parent = divisor_group.DivisorGroup(C)
172            else:
173                raise TypeError, \
174                      "Argument v (= %s) must consist of multiplicities and points on a scheme."
175        else:
176            if not isinstance(parent, divisor_group.DivisorGroup_curve):
177                raise TypeError, "parent (of type %s) must be a DivisorGroup_curve"%type(parent)
178            C = parent.scheme()
179
180        if len(v) < 1:
181            check = False
182        know_points = False
183        if check:
184            w = []
185            points = []
186            know_points = True
187            for t in v:
188                if isinstance(t, tuple) and len(t) == 2:
189                    n = ZZ(t[0])
190                    I = t[1]
191                    points.append((n,I))
192                else:
193                    n = ZZ(1)
194                    I = t
195                if is_SchemeMorphism(I):
196                    I = CurvePointToIdeal(C,I)
197                else:
198                    know_points = False
199                w.append((n,I))
200            v = w
201        Divisor_generic.__init__(
202            self, v, check=False, reduce=True, parent=parent)
203
204        if know_points:
205            self.__points = points
206
207    def _repr_(self):
208        ideals = [ z[1] for z in self ]
209        coeffs = [ z[0] for z in self ]
210        polys = [ tuple(I.gens()) for I in ideals ]
211        return sage.misc.misc.repr_lincomb(polys, coeffs)
212
213    def support(self):
214        """
215        Return the support of this divisor, which is the set of points
216        that occur in this divisor with nonzero coefficients.
217
218        EXAMPLES:
219            sage: x,y = AffineSpace(2, GF(5), names='xy').gens()
220            sage: C = Curve(y^2 - x^9 - x)
221            sage: pts = C.rational_points(); pts
222            [(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
223            sage: D = C.divisor([(3,pts[0]), (-1, pts[1])]); D
224            -(3 + y, 3 + x) + 3*(y, x)
225            sage: D.support()
226            [(0, 0), (2, 2)]
227        """
228        try:
229            return self.__support
230        except AttributeError:
231            try:
232                self.__support = [s[1] for s in self.__points]
233                return self.__support
234            except AttributeError:
235                raise NotImplementedError
236
237    def coeff(self, P):
238        """
239        Return the coefficient of a given point P in this divisor.
240
241        EXAMPLES:
242            sage: x,y = AffineSpace(2, GF(5), names='xy').gens()
243            sage: C = Curve(y^2 - x^9 - x)
244            sage: pts = C.rational_points(); pts
245            [(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
246            sage: D = C.divisor(pts[0])
247            sage: D.coeff(pts[0])
248            1
249            sage: D = C.divisor([(3,pts[0]), (-1,pts[1])]); D
250            -(3 + y, 3 + x) + 3*(y, x)
251            sage: D.coeff(pts[0])
252            3
253            sage: D.coeff(pts[1])
254            -1
255        """
256        P = self.parent().scheme()(P)
257        if not(P in self.support()):
258            return ZZ(0)
259        t, i = search(self.support(), P)
260        assert t
261        try:
262            return self.__points[i][0]
263        except AttributeError:
264                raise NotImplementedError
Note: See TracBrowser for help on using the repository browser.