Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/interfaces/mwrank.py
8814 views
1
r"""
2
Interface to mwrank
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2005 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# This code is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# General Public License for more details.
14
#
15
# The full text of the GPL is available at:
16
#
17
# http://www.gnu.org/licenses/
18
#*****************************************************************************
19
20
import os, weakref
21
from expect import Expect
22
23
instances={}
24
def Mwrank(options="", server=None, server_tmpdir=None):
25
"""
26
Create and return an mwrank interpreter, with given options.
27
28
INPUT:
29
30
- ``options`` - string; passed when starting mwrank.
31
The format is::
32
33
-h help prints this info and quits
34
-q quiet turns OFF banner display and prompt
35
-v n verbosity sets verbosity to n (default=1)
36
-o PARI/GP output turns ON extra PARI/GP short output (default is OFF)
37
-p n precision sets precision to n decimals (default=15)
38
-b n quartic bound bound on quartic point search (default=10)
39
-x n n aux number of aux primes used for sieving (default=6)
40
-l list turns ON listing of points (default ON unless v=0)
41
-s selmer_only if set, computes Selmer rank only (default: not set)
42
-d skip_2nd_descent if set, skips the second descent for curves with 2-torsion (default: not set)
43
-S n sat_bd upper bound on saturation primes (default=100, -1 for automatic)
44
45
.. warning:
46
47
Do not use the option "-q" which turns off the prompt.
48
49
EXAMPLES::
50
51
sage: M = Mwrank('-v 0 -l')
52
sage: print M('0 0 1 -1 0')
53
Curve [0,0,1,-1,0] : Rank = 1
54
Generator 1 is [0:-1:1]; height 0.0511114082399688
55
Regulator = 0.0511114082399688
56
"""
57
global instances
58
try:
59
X = instances[options]()
60
if X:
61
return X
62
except KeyError:
63
pass
64
X = Mwrank_class(options, server=server,server_tmpdir=server_tmpdir)
65
instances[options] = weakref.ref(X)
66
return X
67
68
import re
69
# regex matching '[a1,a2,a3,a4,a6]', no spaces, each ai a possibly signed integer
70
AINVS_LIST_RE = re.compile(r'\[[+-]?(\d+)(,[+-]?\d+){4}]')
71
# regex matching ' a1 a2 a3 a4 a6 ', any whitespace, each ai a possibly signed integer
72
AINVS_PLAIN_RE = re.compile(r'^(\s*)([+-]?(\d+)(\s+)){4}([+-]?(\d+))(\s*)$')
73
74
75
def validate_mwrank_input(s):
76
r"""
77
Returns a string suitable for mwrank input, or raises an error.
78
79
INPUT:
80
81
- `s` -- one of the following:
82
83
- a list or tuple of 5 integers [a1,a2,a3,a4,a6] or (a1,a2,a3,a4,a6)
84
- a string of the form '[a1,a2,a3,a4,a6]' or 'a1 a2 a3 a4 a6' where a1, a2, a3, a4, a6 are integers
85
86
OUTPUT:
87
88
For valid input, a string of the form '[a1,a2,a3,a4,a6]'. For invalid input a ValueError is raised.
89
90
EXAMPLES:
91
92
A list or tuple of 5 integers::
93
94
sage: from sage.interfaces.mwrank import validate_mwrank_input
95
sage: validate_mwrank_input([1,2,3,4,5])
96
'[1, 2, 3, 4, 5]'
97
sage: validate_mwrank_input((-1,2,-3,4,-55))
98
'[-1, 2, -3, 4, -55]'
99
sage: validate_mwrank_input([1,2,3,4])
100
Traceback (most recent call last):
101
...
102
ValueError: [1, 2, 3, 4] is not valid input to mwrank (should have 5 entries)
103
sage: validate_mwrank_input([1,2,3,4,i])
104
Traceback (most recent call last):
105
...
106
ValueError: [1, 2, 3, 4, I] is not valid input to mwrank (entries should be integers)
107
108
109
A string of the form '[a1,a2,a3,a4,a6]' with any whitespace and integers ai::
110
111
sage: validate_mwrank_input('0 -1 1 -7 6')
112
'[0,-1,1,-7,6]'
113
sage: validate_mwrank_input("[0,-1,1,0,0]\n")
114
'[0,-1,1,0,0]'
115
sage: validate_mwrank_input('0\t -1\t 1\t 0\t 0\n')
116
'[0,-1,1,0,0]'
117
sage: validate_mwrank_input('0 -1 1 -7 ')
118
Traceback (most recent call last):
119
...
120
ValueError: 0 -1 1 -7 is not valid input to mwrank
121
122
"""
123
if isinstance(s,(list,tuple)):
124
from sage.rings.all import ZZ
125
if len(s)!=5:
126
raise ValueError, "%s is not valid input to mwrank (should have 5 entries)" % s
127
try:
128
ai = [ZZ(a) for a in s]
129
return str(ai)
130
except (TypeError,ValueError):
131
raise ValueError, "%s is not valid input to mwrank (entries should be integers)" % s
132
133
if isinstance(s,str):
134
if AINVS_PLAIN_RE.match(s):
135
ai = s.split()
136
return "["+",".join(ai)+"]"
137
ss = s.replace(' ','').replace('\n','').replace('\t','')
138
if AINVS_LIST_RE.match(ss):
139
return ss
140
raise ValueError, "%s is not valid input to mwrank" % s
141
142
class Mwrank_class(Expect):
143
"""
144
Interface to the Mwrank interpreter.
145
"""
146
def __init__(self, options="", server=None,server_tmpdir=None):
147
"""
148
INPUT:
149
150
151
- ``options`` - string; passed when starting mwrank.
152
The format is::
153
154
-h help prints this info and quits
155
-q quiet turns OFF banner display and prompt
156
-v n verbosity sets verbosity to n (default=1)
157
-o PARI/GP output turns ON extra PARI/GP short output (default is OFF)
158
-p n precision sets precision to n decimals (default=15)
159
-b n quartic bound bound on quartic point search (default=10)
160
-x n n aux number of aux primes used for sieving (default=6)
161
-l list turns ON listing of points (default ON unless v=0)
162
-s selmer_only if set, computes Selmer rank only (default: not set)
163
-d skip_2nd_descent if set, skips the second descent for curves with 2-torsion (default: not set)
164
-S n sat_bd upper bound on saturation primes (default=100, -1 for automatic)
165
166
.. warning:
167
168
Do not use the option "-q" which turns off the prompt.
169
170
171
.. note::
172
173
Normally instances of this class would be created by
174
calling the global function :meth:`Mwrank`.
175
176
EXAMPLES::
177
178
sage: from sage.interfaces.mwrank import Mwrank_class
179
sage: M = Mwrank_class('-v 0 -l')
180
sage: M('0 -1 1 0 0')
181
'Curve [0,-1,1,0,0] :\tRank = 0\n\n\nRegulator = 1\n'
182
183
sage: from sage.interfaces.mwrank import Mwrank_class
184
sage: TestSuite(Mwrank_class).run()
185
"""
186
Expect.__init__(self,
187
name = 'mwrank',
188
prompt = 'Enter curve: ',
189
command = "mwrank %s"%options,
190
server = server,
191
server_tmpdir = server_tmpdir,
192
maxread = 10000,
193
restart_on_ctrlc = True,
194
verbose_start = False)
195
196
def __getattr__(self, attrname):
197
"""
198
Standard function to return an attribute.
199
200
EXAMPLES::
201
202
sage: mwrank.zzz
203
Traceback (most recent call last):
204
...
205
AttributeError
206
"""
207
raise AttributeError
208
209
def __reduce__(self):
210
"""
211
EXAMPLES::
212
213
sage: mwrank.__reduce__()
214
(<function _reduce_load_mwrank at 0x...>, ())
215
"""
216
217
return _reduce_load_mwrank, tuple([])
218
219
def __call__(self, cmd):
220
"""
221
Interface to eval method.
222
223
INPUT:
224
225
- ``cmd`` A string, or Sage object which when converted to a
226
string gives valid input to ``mwrank``. The conversion is
227
done by :meth:`validate_mwrank_input`.
228
229
EXAMPLES:
230
231
The input can be five integers separated by whitespace::
232
233
sage: mwrank('0 -1 1 0 0')
234
'Curve [0,-1,1,0,0] :\tBasic pair: I=16, J=-304\n...'
235
236
Or a list or tuple of exactly five integers::
237
238
sage: s = mwrank([0,-1,1,0,0])
239
sage: "Rank = 0" in s and "been determined unconditionally" in s
240
True
241
242
TESTS:
243
244
Invalid input raises an ValueError (see #10108); this includes
245
syntactically valid input which defines a singular curve::
246
247
sage: mwrank(10)
248
Traceback (most recent call last):
249
...
250
ValueError: Invalid input: 10 is not valid input to mwrank
251
252
sage: mwrank('0 0 0 0 0')
253
Traceback (most recent call last):
254
...
255
ValueError: Invalid input ([0,0,0,0,0]) to mwrank (singular curve)
256
257
sage: mwrank('0 0 0 -3 2')
258
Traceback (most recent call last):
259
...
260
ValueError: Invalid input ([0,0,0,-3,2]) to mwrank (singular curve)
261
262
"""
263
try:
264
s = validate_mwrank_input(cmd)
265
except ValueError as err:
266
raise ValueError, "Invalid input: %s" % err
267
try:
268
return self.eval(s)
269
except ValueError as err:
270
raise ValueError, err
271
except RuntimeError:
272
raise ValueError, cmd
273
274
def eval(self, s, **kwds):
275
"""
276
Return mwrank's output for the given input.
277
278
INPUT:
279
280
- ``s`` (str) - a Sage object which when converted to a string
281
gives valid input to ``mwrank``. The conversion is done by
282
:meth:`validate_mwrank_input`. Possible formats are:
283
284
- a string representing exactly five integers separated by
285
whitespace, for example '1 2 3 4 5'
286
287
- a string representing exactly five integers separated by
288
commas, preceded by '[' and followed by ']' (with
289
arbitrary whitespace), for example '[1 2 3 4 5]'
290
291
- a list or tuple of exactly 5 integers.
292
293
.. note::
294
295
If a RuntimeError exception is raised, then the mwrank
296
interface is restarted and the command is retried once.
297
298
EXAMPLES::
299
300
sage: mwrank.eval('12 3 4 5 6')
301
'Curve [12,3,4,5,6] :...'
302
sage: mwrank.eval('[12, 3, 4, 5, 6]')
303
'Curve [12,3,4,5,6] :...'
304
sage: mwrank.eval([12, 3, 4, 5, 6])
305
'Curve [12,3,4,5,6] :...'
306
sage: mwrank.eval((12, 3, 4, 5, 6))
307
'Curve [12,3,4,5,6] :...'
308
"""
309
if self._expect is not None and not self._expect.isalive():
310
# if mwrank is interrupted twice in rapid succession,
311
# then it doesn't restart correctly, and we're left with:
312
# "RuntimeError: [Errno 9] Bad file descriptor"
313
# Doing _start again fixes that always. See trac #5157.
314
self._start()
315
try:
316
ss = validate_mwrank_input(s)
317
return Expect.eval(self, ss, **kwds)
318
except ValueError as err:
319
raise ValueError, 'Invalid input: %s' % err
320
except RuntimeError:
321
raise ValueError, 'Invalid input (%s) to mwrank (singular curve)' % s
322
323
def console(self):
324
"""
325
Start the mwrank console.
326
327
EXAMPLE::
328
329
sage: mwrank.console() # not tested: expects console input
330
Program mwrank: ...
331
332
"""
333
mwrank_console()
334
335
def quit(self, verbose=False):
336
"""
337
Quit the mwrank process using kill -9 (so exit doesn't dump core, etc.).
338
339
INPUT:
340
341
- ``verbose`` -- ignored
342
343
EXAMPLES::
344
345
sage: m = Mwrank()
346
sage: e = m('1 2 3 4 5')
347
sage: m.quit()
348
"""
349
if self._expect is None: return
350
try:
351
os.kill(self._expect.pid, 9)
352
except OSError:
353
pass
354
self._expect = None
355
356
357
# An instance
358
mwrank = Mwrank()
359
360
def _reduce_load_mwrank():
361
"""
362
Return the standard mwrank instance
363
364
EXAMPLES::
365
366
sage: from sage.interfaces.mwrank import _reduce_load_mwrank
367
sage: _reduce_load_mwrank()
368
Mwrank
369
"""
370
return mwrank
371
372
import os
373
def mwrank_console():
374
"""
375
Start the mwrank console.
376
377
EXAMPLE::
378
379
sage: mwrank_console() # not tested: expects console input
380
Program mwrank: ...
381
"""
382
os.system('mwrank')
383
384
385