Created
August 23, 2017 16:22
-
-
Save mforets/26d42220946fba8f8e1feb8208783231 to your computer and use it in GitHub Desktop.
Sagemath interface to Julia interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
r""" | |
Interface to Julia interpreter. | |
Julia is a high-level, high-performance dynamic programming language for | |
numerical computing, see the official website <JuliaLang https://julialang.org/>_ | |
for installation and further information. | |
The commands in this section only work if you have "julia" installed and | |
available in your PATH. It's not necessary to install any special Sage packages. | |
EXAMPLES:: | |
sage: julia.eval('2+2') # optional - julia | |
'4\n' | |
:: | |
sage: a = julia(10) # optional - julia | |
sage: a**10 # optional - julia | |
10000000000 | |
AUTHORS: | |
- Marcelo Forets (2017-08-20) : initial implementation, strongly based on the | |
matlab.py interface by W. Stein and D. Joyner. | |
Tutorial | |
-------- | |
EXAMPLES:: | |
sage: julia('4+10') # optional - julia | |
14 | |
sage: julia('5*10 + 6') # optional - julia | |
56 | |
sage: julia('(6+6)/3') # optional - julia | |
4.0 | |
sage: julia('9')^2 # optional - julia | |
81 | |
sage: a = julia(10); b = julia(20); c = julia(30) # optional - julia | |
sage: avg = (a+b+c)/3; avg # optional - julia | |
20.0 | |
sage: parent(avg) # optional - julia | |
Julia | |
:: | |
sage: my_scalar = julia('3.1415') # optional - julia | |
sage: my_scalar # optional - julia | |
3.1415 | |
sage: row_vector = julia('[1 5 7]') # optional - julia | |
sage: row_vector # optional - julia | |
1x3 Array{Int64,2}: | |
1 5 7 | |
sage: column_vector = julia('[1 5 7]') # optional - julia | |
3-element Array{Int64,1}: | |
1 | |
5 | |
7 | |
sage: row_vector * column_vector # optional - julia | |
1-element Array{Int64,1}: | |
75 | |
sage: column_vector * row_vector # optional - julia | |
3×3 Array{Int64,2}: | |
1 5 7 | |
5 25 35 | |
7 35 49 | |
:: | |
sage: row_vector1 = julia('[1 2 3]') # optional - julia | |
sage: row_vector2 = julia('[3 2 1]') # optional - julia | |
sage: matrix_from_row_vec = julia('[%s; %s]'%(row_vector1.name(), row_vector2.name())) # optional - julia | |
sage: matrix_from_row_vec # optional - julia | |
1 2 3 | |
3 2 1 | |
:: | |
sage: column_vector1 = julia('[1;3]') # optional - julia | |
sage: column_vector2 = julia('[2;8]') # optional - julia | |
sage: matrix_from_col_vec = julia('[%s %s]'%(column_vector1.name(), column_vector2.name())) # optional - julia | |
sage: matrix_from_col_vec # optional - julia | |
1 2 | |
3 8 | |
:: | |
sage: my_matrix = julia('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') # optional - julia | |
sage: my_matrix # optional - julia | |
8 12 19 | |
7 3 2 | |
12 4 23 | |
8 1 1 | |
:: | |
sage: combined_matrix = julia('[%s, %s]'%(my_matrix.name(), my_matrix.name())) # optional - julia | |
sage: combined_matrix # optional - julia | |
8 12 19 8 12 19 | |
7 3 2 7 3 2 | |
12 4 23 12 4 23 | |
8 1 1 8 1 1 | |
:: | |
sage: tm = julia('0.5:2:10') # optional - julia | |
sage: tm # optional - julia | |
0.5000 2.5000 4.5000 6.5000 8.5000 | |
:: | |
sage: my_vector1 = julia('[1,5,7]') # optional - julia | |
sage: my_vector1(1) # optional - julia | |
1 | |
sage: my_vector1(2) # optional - julia | |
5 | |
sage: my_vector1(3) # optional - julia | |
7 | |
Matrix indexing works as follows:: | |
sage: my_matrix = julia('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') # optional - julia | |
sage: my_matrix(3,2) # optional - julia | |
4 | |
Setting using parenthesis cannot work (because of how the Python | |
language works). Use square brackets or the set function:: | |
sage: my_matrix = julia('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') # optional - julia | |
sage: my_matrix.set(2,3, 1999) # optional - julia | |
sage: my_matrix # optional - julia | |
8 12 19 | |
7 3 1999 | |
12 4 23 | |
8 1 1 | |
""" | |
#***************************************************************************** | |
# Copyright (C) 2017 Marcelo Forets <mforets@gmail.com> | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 2 of the License, or | |
# (at your option) any later version. | |
# http://www.gnu.org/licenses/ | |
#***************************************************************************** | |
from __future__ import print_function | |
from __future__ import absolute_import | |
import os | |
from .expect import Expect, ExpectElement | |
from sage.docs.instancedoc import instancedoc | |
class Julia(Expect): | |
""" | |
Interface to the julia interpreter. | |
EXAMPLES:: | |
sage: a = julia('[1 1 2; 3 5 8; 13 21 33]') # optional - julia | |
sage: b = julia('[1; 3; 13]') # optional - julia | |
sage: c = a * b # optional - julia | |
sage: print(c) # optional - julia | |
3-element Array{Int64, 1}: | |
30 | |
122 | |
505 | |
""" | |
def __init__(self, maxread=None, script_subdirectory=None, | |
logfile=None, server=None,server_tmpdir=None): | |
Expect.__init__(self, | |
name = 'julia', | |
prompt = 'julia> ', | |
command = "sage-native-execute julia -q", | |
server = server, | |
server_tmpdir = server_tmpdir, | |
script_subdirectory = script_subdirectory, | |
restart_on_ctrlc = False, | |
verbose_start = False, | |
logfile = logfile, | |
eval_using_file_cutoff=100) | |
def __reduce__(self): | |
return reduce_load_julia, tuple([]) | |
def _read_in_file_command(self, filename): | |
""" | |
Returns the command used to read in and execute a file in julia. | |
EXAMPLES:: | |
sage: julia._read_in_file_command('/tmp/julia_file') | |
"eval(fileread('/tmp/julia_file'));" | |
Here is an indirect doctest to check that it does indeed work:: | |
sage: m = identity_matrix(ZZ, 10) | |
sage: sm = julia.sage2julia_matrix_string(m) | |
sage: m = julia(sm) # optional - julia | |
""" | |
return "eval(fileread('{0}'));".format(filename) | |
def _quit_string(self): | |
return 'exit()' | |
def _install_hints(self): | |
return """ | |
You must obtain the program Julia in order to use Julia from Sage. | |
You can read all about julia at <julialang.org http://julialang.org/>_. | |
""" | |
def _start(self): | |
Expect._start(self) | |
def whos(self): | |
return self.eval('whos') | |
def set(self, var, value): | |
""" | |
Set the variable var to the given value. | |
""" | |
cmd = '{0}={1};'.format(var, value) | |
out = self.eval(cmd) | |
if out.find("error") != -1: | |
raise TypeError("Error executing code in julia\nCODE:\n\t{0}\njulia ERROR:\n\t{1}".format(cmd, out)) | |
def get(self, var): | |
""" | |
Get the value of the variable var. | |
EXAMPLES:: | |
sage: s = julia.eval('a = 2') # optional - julia | |
sage: julia.get('a') # optional - julia | |
' 2' | |
""" | |
s = self.eval('{0}'.format(var)) | |
return self.strip_answer(s) | |
def strip_answer(self, s): | |
r""" | |
Returns the string s with Julia's answer prompt removed. | |
EXAMPLES:: | |
sage: s = '\nans =\n\n 2\n' | |
sage: julia.strip_answer(s) | |
' 2' | |
""" | |
i = s.find('=') | |
return s[i+1:].strip('\n') | |
def console(self): | |
julia_console() | |
def version(self): | |
return julia_version()[1:] | |
def chdir(self, directory): | |
""" | |
Change julia's current working directory. | |
EXAMPLES:: | |
sage: julia.chdir('/') # optional - julia | |
sage: julia.pwd() # optional - julia | |
/ | |
""" | |
self.eval("cd('{0}')".format(directory)) | |
def sage2julia_matrix_string(self, A): | |
""" | |
Return a Julia matrix from a Sage matrix. | |
INPUT: | |
- ``A`` -- a Sage matrix with entries in the rationals or reals | |
OUTPUT: | |
A string that evaluates to an julia matrix. | |
EXAMPLES:: | |
sage: M33 = MatrixSpace(QQ,3,3) | |
sage: A = M33([1,2,3,4,5,6,7,8,0]) | |
sage: julia.sage2julia_matrix_string(A) # optional - julia | |
'[1, 2, 3; 4, 5, 6; 7, 8, 0]' | |
""" | |
return str(A.rows()).replace('), (', '; ').replace('(', '').replace(')','') | |
def _object_class(self): | |
return JuliaElement | |
@instancedoc | |
class JuliaElement(ExpectElement): | |
def __getitem__(self, n): | |
raise RuntimeError("Use parenthesis for julia matrices instead.") | |
def _matrix_(self, R): | |
r""" | |
Return Sage matrix from this julia element. | |
EXAMPLES:: | |
sage: A = julia('[1 2; 3 4]') # optional - julia | |
sage: matrix(ZZ, A) # optional - julia | |
[1 2] | |
[3 4] | |
sage: A = julia('[1 2; 3 4.5]') # optional - julia | |
sage: matrix(RR, A) # optional - julia | |
[1.00000000000000 2.00000000000000] | |
[3.00000000000000 4.50000000000000] | |
sage: a = julia('eye(50)') # optional - julia | |
sage: matrix(RR, a) # optional - julia | |
50 x 50 dense matrix over Real Field with 53 bits of precision | |
""" | |
raise NotImplementedError("julia to matrix is not implemented (yet)") | |
from sage.matrix.all import matrix | |
julia = self.parent() | |
entries = julia.strip_answer(julia.eval("mat2str({0})".format(self.name()))) | |
entries = entries.strip()[1:-1].replace(';', ' ') | |
entries = [R(_) for _ in entries.split(' ')] | |
nrows, ncols = map(int, str(self.size()).strip().split()) | |
m = matrix(R, nrows, ncols, entries) | |
return m | |
def set(self, i, j, x): | |
P = self._check_valid() | |
z = P(x) | |
P.eval('{0}({1},{2}) = {3}'.format(self.name(), i, j, z.name())) | |
# An instance | |
julia = Julia() | |
def reduce_load_Julia(): | |
return julia | |
def julia_console(): | |
""" | |
This requires that the optional julia program be installed and in | |
your PATH, but no optional Sage packages need be installed. | |
EXAMPLES:: | |
sage: julia_console() # optional - julia; not tested | |
< M A T L A B > | |
Copyright 1984-2006 The MathWorks, Inc. | |
... | |
>> 2+3 | |
ans = | |
5 | |
exit() | |
Typing quit exits the Julia console and returns you to Sage. | |
Julia, like Sage, remembers its history from one session to | |
another. | |
""" | |
from sage.repl.rich_output.display_manager import get_display_manager | |
if not get_display_manager().is_in_terminal(): | |
raise RuntimeError('Can use the console only in the terminal. Try %%julia magics instead.') | |
os.system('julia') | |
def julia_version(): | |
""" | |
Return the version of Julia installed. | |
EXAMPLES:: | |
sage: julia_version() # random; optional - julia | |
v"0.6.0" | |
""" | |
return str(julia('VERSION')).strip() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment