1 | initial version |
Here is a piece of code computing ranks for all congruent number elliptic curves $y^2 = x^3 - k^2x$ with $k$ from $150$ to $180$, well, at most three seconds per curve.
import signal
def get_rank(E):
try:
return E.rank()
except Exception:
print(f'*** ERROR FOR {E}')
# Introduce a handler at timeout to be passed as argument to the signal.signal
def handler(signum, frame):
raise Exception("TIMEOUT")
dic = {}
for k in [150..180]:
E = EllipticCurve(QQ, [-k^2, 0])
# Register the handler inside signal.signal and set timeout
signal.signal(signal.SIGALRM, handler)
signal.alarm(3) # just three seconds for the rank computation, no more
try:
dic[k] = get_rank(E) # computation here as an explicit call in a separate line
except Exception:
dic[k] = None
print(f'k = {k} :: rank = {rk}')
signal.alarm(0) # close the alarm
Results:
sage: dic
{150: 1,
151: 1,
152: 1,
153: 0,
154: 2,
155: None,
156: 1,
157: None,
158: 1,
159: 1,
160: 0,
161: 2,
162: 0,
163: 0,
164: 2,
165: 1,
166: 1,
167: 1,
168: 0,
169: 0,
170: 0,
171: 0,
172: 0,
173: None,
174: 1,
175: 1,
176: 0,
177: 0,
178: 0,
179: 0,
180: 1}
sage:
And the more difficult expected curve with $k=157$, together with two other curves, were not finished in time. So in principle, this should work in the similar case in question...
In your case, something like the following may be of interest:
for data in [ [0, 146, 0, 1556, 0]
, [0, -249730248677555343372, 0, 158929357618867398869672381174059102500, 0]
, [0, 643, 0, -264, 0]]:
signal.signal(signal.SIGALRM, handler)
signal.alarm(60) # sixty seconds for the rank computation, no more
E = EllipticCurve(QQ, data)
try:
dic[k] = get_rank(E) # computation here as an explicit call in a separate line
except Exception:
dic[k] = None
print(f'{E}\nrank = {rk}\n')
signal.alarm(0) # close the alarm
But unfortunately, (i suppose) the second curve was not inside python to catch the signal, who knows, some factorization problems or worse may have been delegated to pari/gp, and even a manual Control+C in the interpreter did not interrupt the loop. I had to manually kill the sage process from an other terminal. (This is a lucky case, sometimes there is no other terminal that can be opened...)
So an other solution was needed. I tried...
import multiprocessing
import traceback
def get_rank(E, dic):
try:
dic[E.a_invariants()] = E.rank(only_use_mwrank=True)
except Exception:
traceback.print_exc()
print(f'*** ERROR FOR {E}')
manager = multiprocessing.Manager()
ranks_dic = manager.dict() # used to record the results of the rank computations
for data in [ [0, 146, 0, 1556, 0]
, [0, -249730248677555343372, 0, 158929357618867398869672381174059102500, 0]
, [0, 643, 0, -264, 0]]:
E = EllipticCurve(QQ, data)
print(f'... starting rank computation for:\n{E}')
P = multiprocessing.Process(target=get_rank, args=(E, ranks_dic))
P.start() # start the computation
P.join(30) # Wait for 30 seconds or until process finishes
if P.is_alive():
print(f"Terminating the rank computation for:\n{data}\n")
P.terminate() # or to be "sure" it is gone...
# P.kill()
print('Computed ranks:')
for a_invarinats, rk in ranks_dic.items():
print(f'rank = {rk} for {a_invarinats}')
Results:
... starting rank computation for:
Elliptic Curve defined by y^2 = x^3 + 146*x^2 + 1556*x over Rational Field
... starting rank computation for:
Elliptic Curve defined by y^2 = x^3 - 249730248677555343372*x^2 + 158929357618867398869672381174059102500*x over Rational Field
Terminating the rank computation for:
[0, -249730248677555343372, 0, 158929357618867398869672381174059102500, 0]
... starting rank computation for:
Elliptic Curve defined by y^2 = x^3 + 643*x^2 - 264*x over Rational Field
Computed ranks:
rank = 0 for (0, 146, 0, 1556, 0)
rank = 0 for (0, 643, 0, -264, 0)
Note that the computations were started one by one, not exactly the intension of the imported package.