Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News Sign UpSign In
| Download

Tutorial for using %julia in Sage Worksheets

Path: julia / julia.py
Views: 1161
1
r"""
2
Pexpect-based interface to Julia
3
4
EXAMPLES::
5
6
TODO
7
8
AUTHORS:
9
-- William Stein (2014-10-26)
10
"""
11
12
##########################################################################
13
#
14
# Copyright (C) 2014 William Stein <[email protected]>
15
#
16
# Distributed under the terms of the GNU General Public License (GPL)
17
#
18
# http://www.gnu.org/licenses/
19
#
20
##########################################################################
21
22
import os, pexpect, random, string
23
24
from uuid import uuid4
25
def uuid():
26
return str(uuid4())
27
28
29
from sage.interfaces.expect import Expect, ExpectElement, ExpectFunction, FunctionElement, gc_disabled
30
from sage.structure.element import RingElement
31
32
PROMPT_LENGTH = 16
33
34
class Julia(Expect):
35
def __init__(self,
36
maxread = 100000,
37
script_subdirectory = None,
38
logfile = None,
39
server = None,
40
server_tmpdir = None):
41
"""
42
Pexpect-based interface to Julia
43
"""
44
self._prompt = 'julia>'
45
Expect.__init__(self,
46
name = 'Julia',
47
prompt = self._prompt,
48
command = "julia",
49
50
maxread = maxread,
51
server = server,
52
server_tmpdir = server_tmpdir,
53
script_subdirectory = script_subdirectory,
54
55
restart_on_ctrlc = False,
56
verbose_start = False,
57
58
logfile = logfile)
59
60
self.__seq = 0
61
self.__in_seq = 1
62
63
def _start(self):
64
"""
65
"""
66
pexpect_env = dict(os.environ)
67
pexpect_env['TERM'] = 'vt100' # we *use* the codes. DUH. I should have thought of this 10 years ago...
68
self._expect = pexpect.spawn(self._Expect__command, logfile=self._Expect__logfile, env=pexpect_env)
69
self._expect.delaybeforesend = 0 # not a good idea for a CAS.
70
self._expect.expect("\x1b\[0Kjulia>")
71
72
def eval(self, code, **ignored):
73
"""
74
"""
75
if isinstance(code, unicode):
76
code = code.encode('utf8')
77
78
START = "\x1b[?2004l\x1b[0m"
79
END = "\x1b[0G\x1b[0K\x1b[0G\x1b[0Kjulia> "
80
if not self._expect:
81
self._start()
82
with gc_disabled():
83
s = self._expect
84
u = uuid()
85
line = code+'\n\n\n\n\n__ans__=ans;println("%s");ans=__ans__;\n'%u
86
s.send(line)
87
s.expect(u)
88
result = s.before
89
self._last_result = result
90
s.expect(u)
91
self._last_result += s.before
92
s.expect(u)
93
self._last_result += s.before
94
i = result.rfind(START)
95
if i == -1:
96
return result
97
result = result[len(START)+i:]
98
i = result.find(END)
99
if i == -1:
100
return result
101
result = result[:i].rstrip()
102
if result.startswith("ERROR:"):
103
julia_error = result.replace("in anonymous at no file",'')
104
raise RuntimeError(julia_error)
105
return result
106
107
def _an_element_impl(self):
108
"""
109
EXAMPLES::
110
111
sage: julia._an_element_impl()
112
0
113
"""
114
return self(0)
115
116
def set(self, var, value):
117
"""
118
Set the variable var to the given value.
119
120
EXAMPLES::
121
122
sage: julia.set('x', '2')
123
sage: julia.get('x')
124
'2'
125
126
TEST:
127
128
It must also be possible to eval the variable by name::
129
130
sage: julia.eval('x')
131
'2'
132
"""
133
cmd = '%s=%s;'%(var, value)
134
out = self.eval(cmd)
135
if '***' in out: #TODO
136
raise TypeError("Error executing code in Sage\nCODE:\n\t%s\nSAGE ERROR:\n\t%s"%(cmd, out))
137
138
def get(self, var):
139
"""
140
EXAMPLES::
141
142
sage: julia.set('x', '2')
143
sage: julia.get('x')
144
'2'
145
"""
146
out = self.eval(var)
147
return out
148
149
def _repr_(self):
150
return 'Julia Interpreter'
151
152
def __reduce__(self):
153
"""
154
EXAMPLES::
155
156
sage: julia.__reduce__()
157
"""
158
return reduce_load_Julia, tuple([])
159
160
def _function_class(self):
161
"""
162
EXAMPLES::
163
164
sage: julia._function_class()
165
<class 'sage.interfaces.julia.JuliaFunction'>
166
"""
167
return JuliaFunction
168
169
def _quit_string(self):
170
"""
171
EXAMPLES::
172
173
sage: julia._quit_string()
174
'quit()'
175
176
sage: l = Julia()
177
sage: l._start()
178
sage: l.quit()
179
sage: l.is_running()
180
False
181
"""
182
return 'quit()'
183
184
def _read_in_file_command(self, filename):
185
"""
186
EXAMPLES::
187
188
sage: julia._read_in_file_command(tmp_filename()) # TODO
189
"""
190
191
192
def trait_names(self):
193
"""
194
EXAMPLES::
195
196
sage: julia.trait_names()
197
['ANY', ..., 'zip']
198
"""
199
s = julia.eval('\t\t')
200
v = []
201
for x in s.split('\x1b[')[:-1]:
202
i = x.find("G")
203
if i != -1:
204
c = x[i+1:].strip()
205
if c and c.isalnum():
206
v.append(c)
207
v.sort()
208
return v
209
210
def kill(self, var):
211
"""
212
EXAMPLES::
213
214
sage: julia.kill('x')
215
Traceback (most recent call last):
216
...
217
NotImplementedError
218
"""
219
raise NotImplementedError
220
221
def console(self):
222
"""
223
Spawn a new Julia command-line session.
224
225
EXAMPLES::
226
227
sage: julia.console() #not tested
228
...
229
"""
230
julia_console()
231
232
def version(self):
233
"""
234
Returns the version of Julia being used.
235
236
EXAMPLES::
237
238
sage: julia.version()
239
'Version information is given by julia.console().'
240
"""
241
return self.eval("versioninfo()")
242
243
def _object_class(self):
244
"""
245
EXAMPLES::
246
247
sage: julia._object_class()
248
<class 'sage.interfaces.julia.JuliaElement'>
249
"""
250
return JuliaElement
251
252
def _function_class(self):
253
"""
254
EXAMPLES::
255
256
sage: julia._function_class()
257
<class 'sage.interfaces.julia.JuliaFunction'>
258
"""
259
return JuliaFunction
260
261
def _function_element_class(self):
262
"""
263
EXAMPLES::
264
265
sage: julia._function_element_class()
266
<class 'sage.interfaces.julia.JuliaFunctionElement'>
267
"""
268
return JuliaFunctionElement
269
270
def _true_symbol(self):
271
"""
272
EXAMPLES::
273
274
sage: julia._true_symbol()
275
'true'
276
"""
277
return 'true'
278
279
def _false_symbol(self):
280
"""
281
EXAMPLES::
282
283
sage: julia._false_symbol()
284
'false'
285
"""
286
return 'false'
287
288
def _equality_symbol(self):
289
"""
290
"""
291
return "=="
292
293
def help(self, command):
294
"""
295
EXAMPLES::
296
297
298
"""
299
if '"' in command:
300
raise ValueError('quote in command name')
301
return self.eval('help("%s")'%command)
302
303
def function_call(self, function, args=None, kwds=None):
304
"""
305
EXAMPLES::
306
307
sage: julia.function_call('sin', ['2'])
308
0.9092974
309
sage: julia.sin(2)
310
0.9092974
311
"""
312
args, kwds = self._convert_args_kwds(args, kwds)
313
self._check_valid_function_name(function)
314
return self.new("%s(%s)"%(function, ",".join([s.name() for s in args])))
315
316
class JuliaElement(ExpectElement):
317
def trait_names(self):
318
# for now... (until I understand types)
319
return self._check_valid().trait_names()
320
321
def __cmp__(self, other):
322
"""
323
EXAMPLES::
324
325
sage: one = julia(1); two = julia(2)
326
sage: one == one
327
True
328
sage: one != two
329
True
330
sage: one < two
331
True
332
sage: two > one
333
True
334
sage: one < 1
335
False
336
sage: two == 2
337
True
338
339
"""
340
P = self._check_valid()
341
if not hasattr(other, 'parent') or P is not other.parent():
342
other = P(other)
343
344
if P.eval('%s == %s'%(self.name(), other.name())) == P._true_symbol():
345
return 0
346
elif P.eval('%s < %s'%(self.name(), other.name())) == P._true_symbol():
347
return -1
348
else:
349
return 1
350
351
def bool(self):
352
"""
353
EXAMPLES::
354
355
sage: julia(2).bool()
356
True
357
sage: julia(0).bool()
358
False
359
sage: bool(julia(2))
360
True
361
"""
362
P = self._check_valid()
363
return P.eval("bool(%s)"%self.name()) == P._true_symbol()
364
365
def _add_(self, right):
366
"""
367
EXAMPLES::
368
369
sage: a = julia(1); b = julia(2)
370
sage: a + b
371
3
372
"""
373
P = self._check_valid()
374
return P.new('%s + %s'%(self._name, right._name))
375
376
def _sub_(self, right):
377
"""
378
EXAMPLES::
379
380
sage: a = julia(1); b = julia(2)
381
sage: a - b
382
-1
383
"""
384
P = self._check_valid()
385
return P.new('%s - %s'%(self._name, right._name))
386
387
def _mul_(self, right):
388
"""
389
EXAMPLES::
390
391
sage: a = julia(1); b = julia(2)
392
sage: a * b
393
2
394
"""
395
P = self._check_valid()
396
return P.new('%s * %s'%(self._name, right._name))
397
398
def _div_(self, right):
399
"""
400
EXAMPLES::
401
402
sage: a = julia(1); b = julia(2)
403
sage: a / b
404
1/2
405
"""
406
P = self._check_valid()
407
return P.new('%s / %s'%(self._name, right._name))
408
409
def __pow__(self, n):
410
"""
411
EXAMPLES::
412
413
sage: a = julia(3)
414
sage: a^3
415
27
416
"""
417
P = self._check_valid()
418
right = P(n)
419
return P.new('%s ^ %s'%(self._name, right._name))
420
421
class JuliaFunctionElement(FunctionElement):
422
def _sage_doc_(self):
423
"""
424
EXAMPLES::
425
426
sage: two = julia(2)
427
sage: two.sin._sage_doc_()
428
'Base.sin(x)\r\n\r\n Compute sine of "x", where "x" is in radians'
429
"""
430
M = self._obj.parent()
431
return M.help(self._name)
432
433
434
class JuliaFunction(ExpectFunction):
435
def _sage_doc_(self):
436
"""
437
EXAMPLES::
438
439
sage: julia.sin._sage_doc_()
440
Traceback (most recent call last):
441
...
442
NotImplementedError
443
"""
444
M = self._parent
445
return M.help(self._name)
446
447
448
def is_JuliaElement(x):
449
"""
450
EXAMPLES::
451
452
sage: from sage.interfaces.julia import is_JuliaElement
453
sage: is_JuliaElement(julia(2))
454
True
455
sage: is_JuliaElement(2)
456
False
457
"""
458
return isinstance(x, JuliaElement)
459
460
# An instance
461
julia = Julia()
462
463
def reduce_load_Julia():
464
"""
465
EXAMPLES::
466
467
sage: from sage.interfaces.julia import reduce_load_Julia
468
sage: reduce_load_Julia()
469
Julia Interpreter
470
"""
471
return julia
472
473
import os
474
def julia_console():
475
"""
476
Spawn a new Julia command-line session.
477
478
EXAMPLES::
479
480
sage: julia.console() #not tested
481
...
482
"""
483
os.system('julia')
484
485