Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/kodaira_symbol.py
4159 views
1
r"""
2
Kodaira symbols
3
4
Kodaira symbols encode the type of reduction of an elliptic curve at a
5
(finite) place.
6
7
The standard notation for Kodaira Symbols is as a string which is one
8
of `\rm{I}_m`, `\rm{II}`, `\rm{III}`, `\rm{IV}`, `\rm{I}^*_m`,
9
`\rm{II}^*`, `\rm{III}^*`, `\rm{IV}^*`, where `m` denotes a
10
non-negative integer. These have been encoded by single integers by
11
different people. For convenience we give here the conversion table
12
between strings, the eclib coding and the PARI encoding.
13
14
+----------------------+----------------+--------------------+
15
| Kodaira Symbol | Eclib coding | PARI Coding |
16
+======================+================+====================+
17
| `\rm{I}_0` | `0` | `1` |
18
+----------------------+----------------+--------------------+
19
| `\rm{I}^*_0` | `1` | `-1` |
20
+----------------------+----------------+--------------------+
21
| `\rm{I}_m` `(m>0)` | `10m` | `m+4` |
22
+----------------------+----------------+--------------------+
23
| `\rm{I}^*_m` `(m>0)` | `10m+1` | `-(m+4)` |
24
+----------------------+----------------+--------------------+
25
| `\rm{II}` | `2` | `2` |
26
+----------------------+----------------+--------------------+
27
| `\rm{III}` | `3` | `3` |
28
+----------------------+----------------+--------------------+
29
| `\rm{IV}` | `4` | `4` |
30
+----------------------+----------------+--------------------+
31
| `\rm{II}^*` | `7` | `-2` |
32
+----------------------+----------------+--------------------+
33
| `\rm{III}^*` | `6` | `-3` |
34
+----------------------+----------------+--------------------+
35
| `\rm{IV}^*` | `5` | `-4` |
36
+----------------------+----------------+--------------------+
37
38
39
AUTHORS:
40
41
- David Roe <[email protected]>
42
43
- John Cremona
44
45
"""
46
47
#*****************************************************************************
48
# Copyright (C) 2007 David Roe <[email protected]>
49
# William Stein <[email protected]>
50
#
51
# Distributed under the terms of the GNU General Public License (GPL)
52
#
53
# This code is distributed in the hope that it will be useful,
54
# but WITHOUT ANY WARRANTY; without even the implied warranty of
55
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56
# General Public License for more details.
57
#
58
# The full text of the GPL is available at:
59
#
60
# http://www.gnu.org/licenses/
61
#*****************************************************************************
62
63
from sage.structure.sage_object import SageObject
64
from sage.rings.integer import Integer
65
import weakref
66
67
class KodairaSymbol_class(SageObject):
68
r"""
69
Class to hold a Kodaira symbol of an elliptic curve over a
70
`p`-adic local field.
71
72
Users should use the ``KodairaSymbol()`` function to construct
73
Kodaira Symbols rather than use the class constructor directly.
74
"""
75
def __init__(self, symbol):
76
r"""
77
Constructor for Kodaira Symbol class.
78
79
INPUT:
80
81
- ``symbol`` (string or integer) -- The string should be a
82
standard string representation (e.g. III*) of a Kodaira
83
symbol, which will be parsed. Alternatively, use the PARI
84
encoding of Kodaira symbols as integers.
85
86
EXAMPLES::
87
88
sage: from sage.schemes.elliptic_curves.kodaira_symbol import KodairaSymbol_class
89
sage: KodairaSymbol_class(14)
90
I10
91
sage: KodairaSymbol_class('III*')
92
III*
93
sage: latex(KodairaSymbol_class('In'))
94
I_n
95
sage: KodairaSymbol_class('In')
96
In
97
"""
98
if not isinstance(symbol, str):
99
n = Integer(symbol)
100
self._n = None
101
if n == 0:
102
raise ValueError, "Kodaira Symbol code number must be nonzero."
103
if n == 1:
104
self._n = 0
105
self._roman = 1
106
self._str = 'I0'
107
self._latex = 'I_0'
108
elif n == 2:
109
self._roman = 2
110
self._str = 'II'
111
self._latex = 'II'
112
elif n == 3:
113
self._roman = 3
114
self._str = 'III'
115
self._latex = 'III'
116
elif n == 4:
117
self._roman = 4
118
self._str = 'IV'
119
self._latex = 'IV'
120
elif n > 4:
121
nu = n - 4
122
self._n = nu
123
self._roman = 1
124
self._str = 'I' + nu.str()
125
self._latex = 'I_{' + nu.str() + '}'
126
elif n == -1:
127
self._roman = 1
128
self._n = 0
129
self._str = 'I0*'
130
self._latex = 'I_0^{*}'
131
elif n == -2:
132
self._roman = 2
133
self._str = 'II*'
134
self._latex = 'II^{*}'
135
elif n == -3:
136
self._roman = 3
137
self._str = 'III*'
138
self._latex = 'III^{*}'
139
elif n == -4:
140
self._roman = 4
141
self._str = 'IV*'
142
self._latex = 'IV^{*}'
143
elif n < -4:
144
nu = -n - 4
145
self._roman = 1
146
self._n = nu
147
self._str = 'I' + nu.str() +'*'
148
self._latex = 'I_' + nu.str() + '^{*}'
149
self._starred = (n < 0)
150
self._pari = n
151
return
152
elif len(symbol) == 0:
153
raise TypeError, "symbol must be a nonempty string"
154
if symbol[0] == "I":
155
symbol = symbol[1:]
156
starred = False
157
if symbol[-1] == "*":
158
starred = True
159
symbol = symbol[:-1]
160
self._starred = starred
161
if symbol in ["I", "II", "V"]: # NB we have already stripped off the leading 'I'
162
self._roman = ["I", "II", "V"].index(symbol) + 2 # =2, 3 or 4
163
self._n = None
164
if starred:
165
sign = -1
166
self._str = "I" + symbol + "*"
167
self._latex = "I" + symbol + "^*"
168
else:
169
sign = 1
170
self._str = "I" + symbol
171
self._latex = "" + self._str + ""
172
if symbol == "I":
173
self._pari = 2 * sign
174
elif symbol == "II":
175
self._pari = 3 * sign
176
elif symbol == "V":
177
self._pari = 4 * sign
178
elif symbol == "n":
179
self._roman = 1
180
self._pari = None
181
self._n = "generic"
182
if starred:
183
self._str = "In*"
184
self._latex = "I_n^*"
185
else:
186
self._str = "In"
187
self._latex = "I_n"
188
elif symbol.isdigit():
189
self._roman = 1
190
self._n = Integer(symbol)
191
if starred:
192
if self._n == 0:
193
self._pari = -1
194
else:
195
self._pari = -self._n - 4
196
self._str = "I" + symbol + "*"
197
self._latex = "I_{%s}^*"%(symbol)
198
else:
199
if self._n == 0:
200
self._pari = 1
201
else:
202
self._pari = self._n + 4
203
self._str = "I" + symbol
204
self._latex = "I_{%s}"%(symbol)
205
else:
206
raise ValueError, "input is not a Kodaira symbol"
207
208
def __repr__(self):
209
r"""
210
Return the string representation of this Kodaira Symbol.
211
212
EXAMPLES::
213
214
sage: from sage.schemes.elliptic_curves.kodaira_symbol import KodairaSymbol_class
215
sage: KS = KodairaSymbol_class(15)
216
sage: str(KS) # indirect doctest
217
'I11'
218
"""
219
return self._str
220
221
def _latex_(self):
222
r"""
223
Return the string representation of this Kodaira Symbol.
224
225
EXAMPLES::
226
227
sage: from sage.schemes.elliptic_curves.kodaira_symbol import KodairaSymbol_class
228
sage: KS = KodairaSymbol_class(15)
229
sage: latex(KS)
230
I_{11}
231
"""
232
return self._latex
233
234
def __cmp__(self, other):
235
r"""
236
Standard comparison function for Kodaira Symbols.
237
238
EXAMPLES::
239
240
sage: from sage.schemes.elliptic_curves.kodaira_symbol import KodairaSymbol_class
241
sage: KS1 = KodairaSymbol_class(15); KS1
242
I11
243
sage: KS2 = KodairaSymbol_class(-34); KS2
244
I30*
245
sage: KS1 < KS2
246
True
247
sage: KS2 < KS1
248
False
249
250
::
251
252
sage: Klist = [KodairaSymbol_class(i) for i in [-10..10] if i!=0]
253
sage: Klist.sort()
254
sage: Klist
255
[I0,
256
I0*,
257
I1,
258
I1*,
259
I2,
260
I2*,
261
I3,
262
I3*,
263
I4,
264
I4*,
265
I5,
266
I5*,
267
I6,
268
I6*,
269
II,
270
II*,
271
III,
272
III*,
273
IV,
274
IV*]
275
276
"""
277
if isinstance(other, KodairaSymbol_class):
278
if (self._n == "generic" and not other._n is None) or (other._n == "generic" and not self._n is None):
279
return cmp(self._starred, other._starred)
280
return cmp(self._str, other._str)
281
else:
282
return cmp(type(self), type(other))
283
284
def _pari_code(self):
285
"""
286
Return the PARI encoding of this Kodaira Symbol.
287
288
EXAMPLES::
289
290
sage: KodairaSymbol('I0')._pari_code()
291
1
292
sage: KodairaSymbol('I10')._pari_code()
293
14
294
sage: KodairaSymbol('I10*')._pari_code()
295
-14
296
sage: [KodairaSymbol(s)._pari_code() for s in ['II','III','IV']]
297
[2, 3, 4]
298
sage: [KodairaSymbol(s)._pari_code() for s in ['II*','III*','IV*']]
299
[-2, -3, -4]
300
"""
301
return self._pari
302
303
_ks_cache = {}
304
def KodairaSymbol(symbol):
305
r"""
306
Returns the specified Kodaira symbol.
307
308
INPUT:
309
310
- ``symbol`` (string or integer) -- Either a string of the form "I0", "I1", ..., "In", "II", "III", "IV", "I0*", "I1*", ..., "In*", "II*", "III*", or "IV*", or an integer encoding a Kodaira symbol using PARI's conventions.
311
312
OUTPUT:
313
314
(KodairaSymbol) The corresponding Kodaira symbol.
315
316
EXAMPLES::
317
318
sage: KS = KodairaSymbol
319
sage: [KS(n) for n in range(1,10)]
320
[I0, II, III, IV, I1, I2, I3, I4, I5]
321
sage: [KS(-n) for n in range(1,10)]
322
[I0*, II*, III*, IV*, I1*, I2*, I3*, I4*, I5*]
323
sage: all([KS(str(KS(n)))==KS(n) for n in range(-10,10) if n!=0])
324
True
325
"""
326
if _ks_cache.has_key(symbol):
327
ks = _ks_cache[symbol]()
328
if not ks is None:
329
return ks
330
ks = KodairaSymbol_class(symbol)
331
_ks_cache[symbol] = weakref.ref(ks)
332
return ks
333
334