Wolfram Client Library for Python の使い方

Sympyとどう違うのか疑問に思ったため学習メモとして残します。

##これはなに？
Mathematica の組込み関数をPythonで使用可能にするライブラリ

正確には Wolfram言語をPythonから使用可能にするライブラリです。
仕組みとしては Wolfram Engineをローカルで起動してPythonから指令を投げるようです。

Mathematicaと言えばMapleとしのぎを削る代数(文字式)計算ソフト
Pythonでは同様の事をするライブラリとしてSympyが既に存在します。

## 結論

- WolframEngineのPythonインターフェースである
- Sympyのようなシンボリック変数定義は出来ない(関数をPython変数に格納は出来る)
- Wolfram言語の約6000の組込み関数群が使用可能 [^1]
- 文字列のWolfram言語の式を評価可能
- 素のままではJupyterに数式表示は出来ない(致命傷)

Sympyとは住み分けというか出来ることが違います。  
文字式を定義して解きたい方はWolfram Engineをそのまま使用されることをお勧めします。


[^1]: 公式ドキュメント https://www.wolfram.com/language/fast-introduction-for-programmers/ja/built-in-functions/
## インストール

pipでインストールできます。

```
pip install wolframclient
```

こちらの環境は WSL(Ubuntu 18.04.2 LTS) + Pipenv + Python 3.6.8 です。
Wolfram Engine (12.0) インストール済です。  
WSLにインストールする際はlibasound2を入れていないとエラーとなるやもしれません。

```
apt-get install libasound2 
```


こちらが公式ブログの記事になります。
https://blog.wolfram.com/2019/05/16/announcing-the-wolfram-client-library-for-python/

また、呼び出される関数はMathematicaのドキュメントを参照してください。
https://reference.wolfram.com/language/#コアとなる言語と構成

### 使用例

```python
from wolframclient.evaluation import WolframLanguageSession
from wolframclient.language import wl, wlexpr
session = WolframLanguageSession()
```

wlは式を評価せず, 評価前の式を出力します。

```python
>>> wl.Select(wl.PrimeQ, wl.Range(5))
Select[PrimeQ, Range[5]]
```
この構文は間違っているため, evaluateで式を評価した場合エラーとなります。

```python
>>> session.evaluate(wlexpr('Select[PrimeQ,Range[5]]'))
Nonatomic expression expected at position 1 in Select[PrimeQ, {1, 2, 3, 4, 5}].
Select[PrimeQ, PackedArray([1, 2, 3, 4, 5], dtype=int8)]
```

正しい構文に直した場合が以下の式です。

```python
>>> session.evaluate(wlexpr('Select[Range[5],PrimeQ]'))
PackedArray([2, 3, 5], dtype=int8)
```


これはMathematicaの挙動と一致しております。(Mathematica 11.3)
![62e34ef5037dc6c2d850b67afd86b843.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153064/ed3816c8-61f2-eb1c-0b37-2946ee52bc31.png)
![339511866a171ef220a0aa458fb26abb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153064/fdf3309d-5806-ebce-54dc-22ee8429db2d.png)

今回使用した Select 関数は https://reference.wolfram.com/language/ref/Select.html?
PrimeQは https://reference.wolfram.com/language/ref/PrimeQ.html.ja

### 数式の表示


数式の表示法については調査中です。Wolfram Engineでは正常に表示できているので表示法はあると思いますが

Wolfram Engineの場合(Jupyter Lab)

```python
TransferFunctionModel[
StateSpaceModel[{{{Subscript[a, 11], Subscript[a, 12]}, {Subscript[a,
21], Subscript[a, 22]}}, {{Subscript[b, 11]}, {Subscript[b,
21]}}, {{Subscript[c, 11], Subscript[c, 12]}}, {{0}}},
SamplingPeriod ->None, SystemsModelLabels -> None], s]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153064/69e486d1-8a46-91db-40f4-eaa19a3a49fc.png)

Wolfram Client Library for Pythonの場合(Jupyter Lab)

```python
>>> session.evaluate(wlexpr('TransferFunctionModel['\
'StateSpaceModel[{{{Subscript[a, 11], Subscript[a, 12]}, {Subscript[a,'\
'21], Subscript[a, 22]}}, {{Subscript[b, 11]}, {Subscript[b,'\
'21]}}, {{Subscript[c, 11], Subscript[c, 12]}}, {{0}}},'\
'SamplingPeriod ->None, SystemsModelLabels -> None], s]'))
```

```python
TransferFunctionModel[(((Plus[Times[Global`s, Subscript[Global`b, 11], Subscript[Global`c, 11]], Times[-1, Subscript[Global`a, 22], Subscript[Global`b, 11], Subscript[Global`c, 11]], << 2 >>, Times[Global`s, Subscript[Global`b, 21], Subscript[Global`c, 12]], Times[-1, Subscript[Global`a, 11], Subscript[Global`b, 21], Subscript[Global`c, 12]]],),), Plus[Power[Global`s, 2], Times[-1, Global`s, Subscript[Global`a, 11]], << 1 >>, Times[-1, Global`s, Subscript[Global`a, 22]], Times[Subscript[Global`a, 11], Subscript[Global`a, 22]]]), Global`s]
```