can one now set a timelimit on operation in sagemath?
My question here is this: Can now (version 9) tell sagemath to set a timeout on some call and have sagemath issue an error (may be exception) if timeout expires and the call have not completed yet? I am mainly interested in integrate
calls, which some take long time.
Here is an example of how this is done in Maple limits the amount of CPU time spent on a computation
restart;
integrand:=(b*x + a)^(3/2)*(d*x + c)^(5/2)/x^7;
try
timelimit(300,int(integrand,x));
print("Finished before time out, good");
catch:
print("opps, timed out");
end try;
Is it possible to do the above directly in sagemath without me having to program the timelimit myself using Process and Queues? I am using sagemath 9 on Linux.
update
I am getting stack dump when implementing the alarm method shown in the answer below. I am not sure why that is. May be I am making an error somewhere. Below is a MWE to reproduce it.
I created a file build_fricas_new_timeout_one_integral.sage
with content
#!/usr/bin/env sage
from sage.all import *
from cysignals.alarm import alarm, AlarmInterrupt, cancel_alarm
var('x a b')
def doTheIntegration():
integrand = tan(x)/(a^3+b^3*tan(x)^2)^(1/3)
fricas.setSimplifyDenomsFlag(fricas.true)
anti=integrate(integrand,x,algorithm="fricas")
return anti
try:
alarm(20)
anti = doTheIntegration()
except AlarmInterrupt:
print("Timed out")
else:
print("Completed OK, anti=",anti)
cancel_alarm()
Then called it as follows sage ./build_fricas_new_timeout_one_integral.sage
then I get this on the screen
>sage ./build_fricas_new_timeout_one_integral.sage
Interrupting FriCAS...
Traceback (most recent call last):
File "/usr/lib/python3.8/site-packages/sage/interfaces/expect.py", line 986, in _eval_line
E.expect(self._prompt)
File "/usr/lib/python3.8/site-packages/pexpect/spawnbase.py", line 343, in expect
return self.expect_list(compiled_pattern_list,
File "/usr/lib/python3.8/site-packages/pexpect/spawnbase.py", line 372, in expect_list
return exp.expect_loop(timeout)
File "/usr/lib/python3.8/site-packages/pexpect/expect.py", line 169, in expect_loop
incoming = spawn.read_nonblocking(spawn.maxread, timeout)
File "/usr/lib/python3.8/site-packages/pexpect/pty_spawn.py", line 500, in read_nonblocking
if (timeout != 0) and select(timeout):
File "/usr/lib/python3.8/site-packages/pexpect/pty_spawn.py", line 450, in select
return select_ignore_interrupts([self.child_fd], [], [], timeout)[0]
File "/usr/lib/python3.8/site-packages/pexpect/utils.py", line 143, in select_ignore_interrupts
return select.select(iwtd, owtd, ewtd, timeout)
File "src/cysignals/signals.pyx", line 320, in cysignals.signals.python_check_interrupt
cysignals.signals.AlarmInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./build_fricas_new_timeout_one_integral.sage.py", line 22, in <module>
anti = doTheIntegration()
File "./build_fricas_new_timeout_one_integral.sage.py", line 17, in doTheIntegration
anti=integrate(integrand,x,algorithm="fricas")
File "/usr/lib/python3.8/site-packages/sage/misc/functional.py", line 753, in integral
return x.integral(*args, **kwds)
File "sage/symbolic/expression.pyx", line 12391, in sage.symbolic.expression.Expression.integral (build/cythonized/sage/symbolic/expression.cpp:64575)
File "/usr/lib/python3.8/site-packages/sage/symbolic/integration/integral.py", line 927, in integrate
return integrator(expression, v, a, b)
File "/usr/lib/python3.8/site-packages/sage/symbolic/integration/external.py", line 386, in fricas_integrator
result = ex.integrate(v)
File "/usr/lib/python3.8/site-packages/sage/interfaces/interface.py", line 680, in __call__
return self._obj.parent().function_call(self._name, [self._obj] + list(args), kwds)
File "/usr/lib/python3.8/site-packages/sage/interfaces/interface.py", line 601, in function_call
return self.new(s)
File "/usr/lib/python3.8/site-packages/sage/interfaces/interface.py", line 370, in new
return self(code)
File "/usr/lib/python3.8/site-packages/sage/interfaces/interface.py", line 296, in __call__
return cls(self, x, name=name)
File "/usr/lib/python3.8/site-packages/sage/interfaces/expect.py", line 1471, in __init__
self._name = parent._create(value, name=name)
File "/usr/lib/python3.8/site-packages/sage/interfaces/interface.py", line 501, in _create
self.set(name, value)
File "/usr/lib/python3.8/site-packages/sage/interfaces/fricas.py", line 589, in set
output = self.eval(cmd, reformat=False)
File "/usr/lib/python3.8/site-packages/sage/interfaces/fricas.py", line 847, in eval
output = Expect.eval(self, code, strip=strip,
File "/usr/lib/python3.8/site-packages/sage/interfaces/expect.py", line 1384, in eval
return '\n'.join([self._eval_line(L, allow_use_file=allow_use_file, **kwds)
File "/usr/lib/python3.8/site-packages/sage/interfaces/expect.py", line 1384, in <listcomp>
return '\n'.join([self._eval_line(L, allow_use_file=allow_use_file, **kwds)
File "/usr/lib/python3.8/site-packages/sage/interfaces/expect.py", line 1017, in _eval_line
self._keyboard_interrupt()
File "/usr/lib/python3.8/site-packages/sage/interfaces/expect.py", line 1039, in _keyboard_interrupt
raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self)
KeyboardInterrupt: Ctrl-c pressed while running FriCAS
>
Am I doing something wrong in using the alarm method?