Juliaは、多くの便利な数値解析ツールが組み込まれた高性能プログラミング言語です。記述が容易で、科学計算、機械学習など、さまざまな分野で役立つパッケージが急速に増えています。Juliaは、JMPと同様に、科学者、研究者、エンジニアにとって非常に貴重なツールです。
Juliaは他のプログラミング言語との相互運用性の高さで定評があり、JSLからJuliaを呼び出すのがどれほど難しいのか興味がありました。もしそれが可能であれば(実際可能です!)、JSLからJuliaを呼び出すことには大きな可能性を感じます。高性能なJuliaプログラムを呼び出す対話型のJMPユーザーインターフェースを構築したり、Juliaでモデルを構築してJMPで結果をプロットしたり、あるいはその逆も可能です。JMPワークフローの遅い部分をJuliaで処理することもできます。
JSLからJuliaを呼び出す2つの方法について説明します。1つ目の方法は、JSLを使ってPythonを呼び出し、PythonからJuliaを呼び出す方法です。2つ目の方法は、C言語で書かれたダイナミックリンクライブラリ(DLL)にJuliaを組み込む方法です。
なお、ここではJuliaでのプログラミングについてはあまり詳しく触れません。Juliaについてもっと知りたい方は、公式ドキュメントをご覧ください。Julia Academyからも学習教材が提供されています。
PythonからJuliaを呼び出す
Python in JSL
JMP 14では、Pythonと直接連携するためのJSLコマンドが追加されました。スクリプト索引から簡単な例を以下に示します。
// Initialize the Python interface
PythonInit();
// Submit some Python code to run as a JSL string
PythonSubmit("\[message = 'The quick brown fox jumps over the lazy dog']\");
// message is now a variable in Python and can be accessed from JSL with PythonGet()
getStr = PythonGet(message);
Show(getStr);
// Terminate the Python interface
PythonTerm();
ピジュリア
PythonからJuliaを呼び出せるなら、JSLからもJuliaを呼び出せるはずです。PyJulia はまさにそれを可能にするPythonパッケージです。早速セットアップしてみましょう。注:私はMac上でJulia 1.5.4、Python 3.9.5、PyJulia 0.5.7、JMP 16.1を使用して正常に動作しました。
Pythonが正常にインストールされていることを前提として、セットアップは以下のとおりです。
まだインストールしていない場合は、Juliaをインストールしてください。インストール手順については、 「公式バイナリのプラットフォーム別手順」をご覧ください。最新バージョンは、 Juliaのダウンロードページからダウンロードできます。
次に、 指示に従ってPyJuliaをインストールしてください。
通常のPythonセッションでPyJuliaの使用方法を理解できるのであれば、準備は万端です!
JSLにおけるPyJulia
JSLでは、まずPythonセッションでJuliaを初期化する必要があります。以下の例のように、Julia実行可能ファイルへのパスをランタイムキーワード引数として渡すようにしてください。
Python Init();
// Initialize julia
Python Submit(
"\[
from julia import Julia
Julia(runtime="/usr/local/bin/julia")
]\");
ここから、 PythonのSubmitコマンドを使って任意のJuliaコードを実行できます。
// Import the main module. This is Julia's workspace.
Python Submit("\[
from julia import Main
Main.xs = [1,2,3] # xs belongs to julia
sines = Main.eval("sin.(xs)") # This returns the sine of each element in xs
]\");
show(PythonGet(sines)); // [0.841470984807897 0.909297426825682 0.141120008059867]
他の Julia パッケージがインストールされている場合は、Python の import コマンドでアクセスできます。ここでは、Pandas.jl、DataFrames.jl、および Lasso.jl を使用して、Big Class.jmp の身長に対して Lasso フィッティングを実行しました。次に、 JMP Graph Builder を使用して、実際の値と予測値をプロットしました。
// Convert datatable to julia dataframe
// Must convert it to a julia Pandas dataframe first
dt = open("$SAMPLE_DATA/Big Class.jmp");
Pythonsend(dt);
Python Submit(
"\[
from julia import Pandas
from julia import DataFrames
from julia import Lasso
Main.dt = dt
predicted = Main.eval("""
using Lasso
df = DataFrames.DataFrame(Pandas.DataFrame(dt))
m = fit(LassoModel, @formula(height ~ sex + weight), df)
predict(m, df)
""")
]\");
// Back to JMP where we plot Actual vs. Predicted
predicted = pythonget("predicted");
dt << newColumn("Predicted height", <
<SETVALUES></SETVALUES>
<P class="lia-align-center" style="text-align: center;" style="text-align: center;"><FONT size="2"><EM>Juliaで計算された結果に基づく、実際の値と予測値のグラフビルダープロット。</EM></FONT></P> <P><SPAN class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="plot.png" style="width: 385px;"><span class="lia-inline-image-display-wrapper" image-alt="plot.png" style="width: 385px;"><img src="https://us.v-cdn.net/6038925/uploads/images/41854i1D3222BA026053FF/plot.png" role="button" title="plot.png" alt="plot.png" /></span><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">plot.png</SPAN></SPAN></P> <BR /> <P><FONT size="5">JuliaをDLLに埋め込む</FONT><BR /><A href="https://docs.julialang.org/en/v1/manual/embedding/" target="_self" rel="nofollow noopener noreferrer">JuliaをC言語のコードに組み込む</A>ことも可能です。いくつか簡単な例を挙げますが、C言語に詳しい方ならさらに高度な使い方ができるでしょう。</P> <P><STRONG><FONT size="4">LoadDLL</FONT></STRONG><BR />ここで重要なのは、JSLの<FONT face="courier new,courier">LoadDLL</FONT>関数です。LoadDLL<FONT face="courier new,courier">の</FONT>使い方を学ぶための優れた資料として、 <A href="https://www.lexjansen.com/nesug/nesug10/ad/ad04.pdf" target="_blank" rel="noopener nofollow noreferrer">こちらの論文</A>があります。簡単な例として、test.cというファイルにある以下のC関数を見てみましょう。</P> // test.c
double myMultiply(double num1, double num2)
{
return num1 * num2;
} そしてDLLにコンパイルする
# On Mac
gcc -shared -o test.dylib test.c
# On Windows
gcc -shared -o test.dll test.c
そしてJMPでは、C関数を呼び出すことができます。
dll = loadDLL(convertfilepath("/path/to/my/test.dylib"));
dll << declareFunction("myMultiply",
Convention( STDCALL ),
Arg(Double, "num1"),
Arg(Double, "num2"),
Returns( Double )
);
show(dll << myMultiply(Pi(), 100));
dll << unloadDLL; ジュリアDLL
それでは、Juliaが組み込まれたDLLを見てみましょう。入力値の正弦を計算する関数を作成します。入力値は度数で表されます。
// call_julia.c
#include
double sineInDegrees(double degrees)
{
// required: setup the Julia context
jl_init();
// You can evaluate Julia code from strings
jl_value_t *factor = jl_eval_string("pi/180");
double factor_unboxed = jl_unbox_float64(factor);
double radians = degrees * factor_unboxed;
// You can call Julia functions directly
jl_function_t *func = jl_get_function(jl_base_module, "sin");
jl_value_t *argument = jl_box_float64(radians);
jl_value_t *ret = jl_call1(func, argument);
double ret_unboxed = jl_unbox_float64(ret);
jl_atexit_hook(0);
return ret_unboxed;
}
Macでコンパイルするには、以下のコマンドを実行してください。ここで、 $JULIA_DIRはJuliaバイナリへのパスを指定する環境変数です。私の場合は、/Applications/Julia-1.7.app/Contents/Resources/juliaでした。Windowsでは試していませんが、同様の方法で動作するはずです。
# On Mac
gcc -shared -o call_julia.dylib call_julia.c -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib -Wl,-rpath,$JULIA_DIR/lib -ljulia
これでJSLでサインInDegreesを呼び出すことができるようになりました!
dll = loadDLL(convertfilepath("/path/to/my/call_julia.dylib"));
dll << declareFunction("sineInDegrees",
Convention( STDCALL ),
Arg( Double, "degrees" ),
Returns( Double )
);
show(dll << sineInDegrees(90)); // 1
dll << unloadDLL; 結論
JSLのPythonおよびLoadDLLインターフェースを使用することで、JMPを超えてJuliaを呼び出すことができます。動作させるまでには試行錯誤が必要でしたが、一度設定が完了すれば非常にうまく機能します。この記事では簡単な例をいくつか紹介しましたが、JMPとJuliaを組み合わせることで、斬新で興味深いアプリケーションを構築できる可能性を秘めていると考えています。
読んでいただきありがとうございます。この記事を通して、皆さんに有益な情報を提供し、さらに探求したいという気持ちになっていただけたなら幸いです。
バージョンに関する注記
Mac 上で Julia 1.5 と Julia 1.8 ベータ版を使用した場合のみ、Python 経由で Julia を動作させることができました。Windows 上では Python 経由で Julia を使用することに成功しませんでしたが、Mac ほど多くのバージョンを試していません。テストにはすべて JMP 16 を使用しました。