茱莉亞是一種高效能程式語言,內建了許多實用的數值分析工具。它易於編寫,並且擁有一個快速發展的生態系統,其中包含大量用於科學計算、機器學習等許多領域的實用軟體包。 Julia 與 JMP 一樣,是科學家、研究人員和工程師不可或缺的工具。
Julia 以其與其他程式語言的良好互通性而聞名,我很好奇從 JSL 呼叫 Julia 會有多難。如果可行(事實證明確實可行!),我認為從 JSL 呼叫 Julia 具有巨大的潛力。您可以建立互動式 JMP 使用者介面,呼叫高效能的 Julia 程式。您可以在 Julia 中建立模型,然後在 JMP 中繪製結果,反之亦然。您可以將 JMP 工作流程中耗時的部分用 Julia 來完成。
我將討論兩種從 JSL 呼叫 Julia 的方法。第一種方法是使用 JSL 呼叫 Python,再由 Python 呼叫 Julia。第二種方法是將 Julia 嵌入到用 C 語言編寫的動態連結庫 (DLL) 中。
請注意,我不會詳細介紹 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();
PyJulia
如果我們可以從 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提交來運行任何 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 匯入來存取它們。這裡我使用了 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();">繪圖.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也可以嵌入</A>到C程式碼中。我會分享一些簡單的例子,但我相信更熟悉C語言的人可以進一步擴展這方面的內容。</P> <P><STRONG><FONT size="4">LoadDLL</FONT></STRONG><BR />關鍵在於 JSL 的<FONT face="courier new,courier">LoadDLL</FONT>函式。 <A href="https://www.lexjansen.com/nesug/nesug10/ad/ad04.pdf" target="_blank" rel="noopener nofollow noreferrer">這篇論文</A>是學習如何使用<FONT face="courier new,courier">LoadDLL 的</FONT>絕佳資源。舉個簡單的例子,我們可以看看 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; Julia 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 中呼叫sinInDegrees了!
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 beta版,透過Python成功運行了Julia。在Windows平台上,我嘗試的Julia版本沒有Mac平台上那麼多,但透過Python運行Julia失敗了。我的所有測試都使用了JMP 16。