version 1.1, 2018/09/08 05:35:35 |
version 1.3, 2019/03/29 02:17:00 |
|
|
# $OpenXM$ |
# $OpenXM: OpenXM/src/sage/asir.py,v 1.2 2019/03/06 02:38:33 takayama Exp $ |
from __future__ import print_function |
from __future__ import print_function |
from __future__ import absolute_import |
from __future__ import absolute_import |
|
|
import os |
import os |
from .expect import Expect, ExpectElement |
from sage.interfaces.expect import Expect, ExpectElement |
from sage.misc.misc import verbose |
from sage.misc.misc import verbose |
|
|
|
##Ref: @s/2018/09/20180907-sage-asir-proj, Using External Libraries and Interfaces |
|
##Ref: /usr/lib/python2.7/dist-packages/sage/interfaces |
|
##Usage: load("asir.py"); |
|
|
class Asir(Expect): |
class Asir(Expect): |
r""" |
r""" |
Interface to the Asir interpreter. |
Interface to the Asir interpreter. |
|
|
EXAMPLES:: |
EXAMPLES:: |
|
|
sage: asir.eval("a = [ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]") # optional - asir |
sage: asir.evall("F=fctr(x^10-1)") # optional - asir |
'a =\n\n 1 1 2\n 3 5 8\n 13 21 33\n\n's |
|
sage: asir.eval("b = [ 1; 3; 13]") # optional - asir |
|
'b =\n\n 1\n 3\n 13\n\n' |
|
sage: asir.eval("c=a \\ b") # solves linear equation: a*c = b # optional - asir; random output |
|
'c =\n\n 1\n 7.21645e-16\n -7.21645e-16\n\n' |
|
sage: asir.eval("c") # optional - asir; random output |
|
'c =\n\n 1\n 7.21645e-16\n -7.21645e-16\n\n' |
|
""" |
""" |
|
|
def __init__(self, maxread=None, script_subdirectory=None, logfile=None, |
def __init__(self, maxread=None, script_subdirectory=None, logfile=None, |
Line 39 class Asir(Expect): |
|
Line 36 class Asir(Expect): |
|
Expect.__init__(self, |
Expect.__init__(self, |
name = 'asir', |
name = 'asir', |
# We want the prompt sequence to be unique to avoid confusion with syntax error messages containing >>> |
# We want the prompt sequence to be unique to avoid confusion with syntax error messages containing >>> |
# prompt = 'asir\:\d+> ', |
|
prompt = 'asir>', |
prompt = 'asir>', |
# prompt = '', |
|
# We don't want any pagination of output |
# We don't want any pagination of output |
# command = command + " --no-line-editing --silent --eval 'PS2(PS1());more off' --persist", |
|
command = 'openxm ox_texmacs --view sage --quiet --noCopyright', |
command = 'openxm ox_texmacs --view sage --quiet --noCopyright', |
# command = "openxm asir -quiet", |
|
maxread = maxread, |
maxread = maxread, |
server = server, |
server = server, |
server_tmpdir = server_tmpdir, |
server_tmpdir = server_tmpdir, |
Line 58 class Asir(Expect): |
|
Line 51 class Asir(Expect): |
|
|
|
def set_seed(self, seed=None): |
def set_seed(self, seed=None): |
""" |
""" |
Sets the seed for the random number generator |
Not implemented. Sets the seed for the random number generator |
for this asir interpreter. |
for this asir interpreter. |
|
|
EXAMPLES:: |
|
|
|
sage: o = Asir() # optional - asir |
|
sage: o.set_seed(1) # optional - asir |
|
1 |
|
sage: [o.rand() for i in range(5)] # optional - asir |
|
[ 0.134364, 0.847434, 0.763775, 0.255069, 0.495435] |
|
""" |
""" |
if seed is None: |
return 0 |
seed = self.rand_seed() |
|
self.eval("rand('state',%d)" % seed) |
|
self._seed = seed |
|
return seed |
|
|
|
def __reduce__(self): |
def __reduce__(self): |
""" |
""" |
Line 90 class Asir(Expect): |
|
Line 71 class Asir(Expect): |
|
|
|
sage: filename = tmp_filename() |
sage: filename = tmp_filename() |
sage: asir._read_in_file_command(filename) |
sage: asir._read_in_file_command(filename) |
'source("...");' |
'load("...");' |
""" |
""" |
return 'source("%s");'%filename |
return 'load("%s");'%filename |
|
|
def _quit_string(self): |
def _quit_string(self): |
""" |
""" |
Line 113 class Asir(Expect): |
|
Line 94 class Asir(Expect): |
|
You must get ... |
You must get ... |
""" |
""" |
return """ |
return """ |
You must get the program "asir" in order to use Asir |
You must get the program "asir" and "ox_texmacs" in order to use Asir |
from Sage. You can read all about Asir at |
from Sage. You can read all about Asir at |
http://www.gnu.org/software/asir/ |
http://www.openxm.org |
|
The command openxm must be in the search path. |
LINUX: |
|
Do apt-get install asir as root on your machine (Ubuntu/Debian). |
|
Other Linux systems have asir too. |
|
|
|
OS X: |
|
* This website has details on OS X builds of Asir: |
|
http://wiki.asir.org/Asir_for_MacOS_X |
|
* Darwin ports and fink have Asir as well. |
|
""" |
""" |
|
def evall(self,cmd): |
|
""" |
|
evalutes the argument immediately. The argument of eval is buffered |
|
and ; should be added. |
|
EXAMPLES:: |
|
sage: asir.eval('1+2;'); asir.evall('3+3') |
|
""" |
|
return self.eval(cmd+';;') |
def _eval_line(self, line, reformat=True, allow_use_file=False, |
def _eval_line(self, line, reformat=True, allow_use_file=False, |
wait_for_prompt=True, restart_if_needed=False): |
wait_for_prompt=True, restart_if_needed=False): |
""" |
""" |
EXAMPLES:: |
EXAMPLES:: |
|
|
sage: print(asir._eval_line('2+2')) #optional - asir |
sage: print(asir._eval_line('2+2')) #optional - asir |
ans = 4 |
'4' |
""" |
""" |
from pexpect.exceptions import EOF |
from pexpect.exceptions import EOF |
if not wait_for_prompt: |
if not wait_for_prompt: |
Line 169 class Asir(Expect): |
|
Line 149 class Asir(Expect): |
|
return '' |
return '' |
|
|
def _keyboard_interrupt(self): |
def _keyboard_interrupt(self): |
print("CntrlC: Interrupting %s..."%self) |
print("Ctrl-C: Interrupting %s..."%self) |
if self._restart_on_ctrlc: |
if self._restart_on_ctrlc: |
try: |
try: |
self._expect.close(force=1) |
self._expect.close(force=1) |
Line 252 class Asir(Expect): |
|
Line 232 class Asir(Expect): |
|
|
|
EXAMPLES:: |
EXAMPLES:: |
|
|
sage: asir.set('x', '2') # optional - asir |
sage: asir.set('X', '2') # optional - asir |
sage: asir.get('x') # optional - asir |
sage: asir.get('X') # optional - asir |
' 2' |
' 2' |
""" |
""" |
cmd = '%s=%s;'%(var,value) |
cmd = '%s=%s'%(var,value) |
out = self.eval(cmd) |
out = self.evall(cmd) |
if out.find("error") != -1 or out.find("Error") != -1: |
if out.find("error") != -1 or out.find("Error") != -1: |
raise TypeError("Error executing code in Asir\nCODE:\n\t%s\nAsir ERROR:\n\t%s"%(cmd, out)) |
raise TypeError("Error executing code in Asir\nCODE:\n\t%s\nAsir ERROR:\n\t%s"%(cmd, out)) |
|
|
Line 267 class Asir(Expect): |
|
Line 247 class Asir(Expect): |
|
|
|
EXAMPLES:: |
EXAMPLES:: |
|
|
sage: asir.set('x', '2') # optional - asir |
sage: asir.set('X', '2') # optional - asir |
sage: asir.get('x') # optional - asir |
sage: asir.get('X') # optional - asir |
' 2' |
' 2' |
""" |
""" |
s = self.eval('%s;'%var) |
s = self.evall('%s;'%var) |
i = s.find('=') |
i = s.find('=') |
return s[i+1:] |
return s[i+1:] |
|
|
def clear(self, var): |
|
""" |
|
Clear the variable named var. |
|
|
|
EXAMPLES:: |
|
|
|
sage: asir.set('x', '2') # optional - asir |
|
sage: asir.clear('x') # optional - asir |
|
sage: asir.get('x') # optional - asir |
|
"error: 'x' undefined near line ... column 1" |
|
""" |
|
self.eval('clear %s'%var) |
|
|
|
def console(self): |
def console(self): |
""" |
""" |
Spawn a new Asir command-line session. |
Spawn a new Asir command-line session. |
Line 297 class Asir(Expect): |
|
Line 264 class Asir(Expect): |
|
|
|
EXAMPLES:: |
EXAMPLES:: |
|
|
sage: asir_console() # not tested |
sage: asir_console() |
GNU Asir, version 2.1.73 (i386-apple-darwin8.5.3). |
This is Risa/Asir, .... |
Copyright (C) 2006 John W. Eaton. |
|
... |
... |
asir:1> 2+3 |
[nnnn] 2+3; |
ans = 5 |
5 |
asir:2> [ctl-d] |
[nnnn] quit(); |
|
|
Pressing ctrl-d exits the asir console and returns you to Sage. |
quit(); exits the asir console and returns you to Sage. |
asir, like Sage, remembers its history from one session to |
|
another. |
|
""" |
""" |
asir_console() |
asir_console() |
|
|
def version(self): |
def version(self): |
""" |
""" |
Return the version of Asir. |
Return the version of Asir. |
|
bug: it returns error because sage tries to set sage0=version(); |
|
insread of Sage0=version(); |
OUTPUT: string |
OUTPUT: string |
|
|
EXAMPLES:: |
EXAMPLES:: |
Line 323 class Asir(Expect): |
|
Line 288 class Asir(Expect): |
|
sage: v # optional - asir; random |
sage: v # optional - asir; random |
'2.13.7' |
'2.13.7' |
|
|
sage: import re |
|
sage: assert re.match("\d+\.\d+\.\d+", v) is not None # optional - asir |
|
""" |
""" |
return str(self("version()")).strip() |
return str(self("version()")).strip() |
|
|
def solve_linear_system(self, A, b): |
|
r""" |
|
Use asir to compute a solution x to A\*x = b, as a list. |
|
|
|
INPUT: |
|
|
|
- ``A`` -- mxn matrix A with entries in `\QQ` or `\RR` |
|
|
|
- ``b`` -- m-vector b entries in `\QQ` or `\RR` (resp) |
|
|
|
OUTPUT: A list x (if it exists) which solves M\*x = b |
|
|
|
EXAMPLES:: |
|
|
|
sage: M33 = MatrixSpace(QQ,3,3) |
|
sage: A = M33([1,2,3,4,5,6,7,8,0]) |
|
sage: V3 = VectorSpace(QQ,3) |
|
sage: b = V3([1,2,3]) |
|
sage: asir.solve_linear_system(A,b) # optional - asir (and output is slightly random in low order bits) |
|
[-0.33333299999999999, 0.66666700000000001, -3.5236600000000002e-18] |
|
|
|
AUTHORS: |
|
|
|
- David Joyner and William Stein |
|
""" |
|
m = A.nrows() |
|
if m != len(b): |
|
raise ValueError("dimensions of A and b must be compatible") |
|
from sage.matrix.all import MatrixSpace |
|
from sage.rings.all import QQ |
|
MS = MatrixSpace(QQ,m,1) |
|
b = MS(list(b)) # converted b to a "column vector" |
|
sA = self.sage2asir_matrix_string(A) |
|
sb = self.sage2asir_matrix_string(b) |
|
self.eval("a = " + sA ) |
|
self.eval("b = " + sb ) |
|
soln = asir.eval("c = a \\ b") |
|
soln = soln.replace("\n\n ","[") |
|
soln = soln.replace("\n\n","]") |
|
soln = soln.replace("\n",",") |
|
sol = soln[3:] |
|
return eval(sol) |
|
|
|
|
|
def sage2asir_matrix_string(self, A): |
|
""" |
|
Return an asir matrix from a Sage matrix. |
|
|
|
INPUT: A Sage matrix with entries in the rationals or reals. |
|
|
|
OUTPUT: A string that evaluates to an Asir matrix. |
|
|
|
EXAMPLES:: |
|
|
|
sage: M33 = MatrixSpace(QQ,3,3) |
|
sage: A = M33([1,2,3,4,5,6,7,8,0]) |
|
sage: asir.sage2asir_matrix_string(A) # optional - asir |
|
'[1, 2, 3; 4, 5, 6; 7, 8, 0]' |
|
|
|
AUTHORS: |
|
|
|
- David Joyner and William Stein |
|
""" |
|
return str(A.rows()).replace('), (', '; ').replace('(', '').replace(')','') |
|
|
|
def de_system_plot(self, f, ics, trange): |
|
r""" |
|
Plots (using asir's interface to gnuplot) the solution to a |
|
`2\times 2` system of differential equations. |
|
|
|
INPUT: |
|
|
|
|
|
- ``f`` - a pair of strings representing the |
|
differential equations; The independent variable must be called x |
|
and the dependent variable must be called y. |
|
|
|
- ``ics`` - a pair [x0,y0] such that x(t0) = x0, y(t0) |
|
= y0 |
|
|
|
- ``trange`` - a pair [t0,t1] |
|
|
|
|
|
OUTPUT: a gnuplot window appears |
|
|
|
EXAMPLES:: |
|
|
|
sage: asir.de_system_plot(['x+y','x-y'], [1,-1], [0,2]) # not tested -- does this actually work (on OS X it fails for me -- William Stein, 2007-10) |
|
|
|
This should yield the two plots `(t,x(t)), (t,y(t))` on the |
|
same graph (the `t`-axis is the horizontal axis) of the |
|
system of ODEs |
|
|
|
.. math:: |
|
|
|
x' = x+y, x(0) = 1;\qquad y' = x-y, y(0) = -1, \quad\text{for}\quad 0 < t < 2. |
|
""" |
|
eqn1 = f[0].replace('x','x(1)').replace('y','x(2)') |
|
eqn2 = f[1].replace('x','x(1)').replace('y','x(2)') |
|
fcn = "function xdot = f(x,t) xdot(1) = %s; xdot(2) = %s; endfunction"%(eqn1, eqn2) |
|
self.eval(fcn) |
|
x0_eqn = "x0 = [%s; %s]"%(ics[0], ics[1]) |
|
self.eval(x0_eqn) |
|
t_eqn = "t = linspace(%s, %s, 200)'"%(trange[0], trange[1]) |
|
self.eval(t_eqn) |
|
x_eqn = 'x = lsode("f",x0,t);' |
|
self.eval(x_eqn) |
|
self.eval("plot(t,x)") |
|
|
|
def _object_class(self): |
def _object_class(self): |
""" |
""" |
EXAMPLES:: |
EXAMPLES:: |
Line 449 class Asir(Expect): |
|
Line 303 class Asir(Expect): |
|
|
|
asir_functions = set() |
asir_functions = set() |
|
|
def to_complex(asir_string, R): |
#Todo, the following class has not yet been implemented. |
r""" |
# These are sample interface with octave. |
Helper function to convert asir complex number |
|
|
|
TESTS:: |
|
|
|
sage: from sage.interfaces.asir import to_complex |
|
sage: to_complex('(0,1)', CDF) |
|
1.0*I |
|
sage: to_complex('(1.3231,-0.2)', CDF) |
|
1.3231 - 0.2*I |
|
""" |
|
real, imag = asir_string.strip('() ').split(',') |
|
return R(float(real), float(imag)) |
|
|
|
class AsirElement(ExpectElement): |
class AsirElement(ExpectElement): |
def _get_sage_ring(self): |
def _get_sage_ring(self): |
r""" |
r""" |
Line 680 def asir_console(): |
|
Line 521 def asir_console(): |
|
EXAMPLES:: |
EXAMPLES:: |
|
|
sage: asir_console() # not tested |
sage: asir_console() # not tested |
GNU Asir, version 2.1.73 (i386-apple-darwin8.5.3). |
This is Risa/Asir .... |
Copyright (C) 2006 John W. Eaton. |
|
... |
... |
asir:1> 2+3 |
[nnnn] 2+3; |
ans = 5 |
5 |
asir:2> [ctl-d] |
[nnnn] quit(); |
|
|
Pressing ctrl-d exits the asir console and returns you to Sage. |
quit(); exits the asir console and returns you to Sage. |
asir, like Sage, remembers its history from one session to |
|
another. |
|
""" |
""" |
from sage.repl.rich_output.display_manager import get_display_manager |
from sage.repl.rich_output.display_manager import get_display_manager |
if not get_display_manager().is_in_terminal(): |
if not get_display_manager().is_in_terminal(): |
raise RuntimeError('Can use the console only in the terminal. Try %%asir magics instead.') |
raise RuntimeError('Can use the console only in the terminal. Try %%asir magics instead.') |
os.system('openxm asir') # with asir prompt |
os.system('openxm fep asir') # with asir prompt |
# os.system('openxm asir -quiet') |
# os.system('openxm asir -quiet') |
|
|
|
|