Mathematica の Open XM 化について

小原功任

November 25, 1999

1 我々が提供するもの

我々が提供するのは二つのプログラムとそのソースである。一つ目は ox math プログラムであり、これは OpenXM サーバの一種である。二つ目は math2ox であり、 OpenXM クライアントである。

2 Open Mathematica サーバの構成

Open Mathmatica サーバは Open XM クライアントおよび mathematica カーネルと通信する。 Open Mathmatica サーバは起動直後に mathematica カーネルを起動し、 mathematica カーネルと協調して動作する。 mathematica カーネルとは MathLink ライブラリを利用して通信する。 Open Mathmatica サーバは MathLink のラッパだと思ってよい。 Open XM クライアントとの間はソケットを利用して通信する。 Open Mathmatica サーバはファイルディスクリプタ 3,4 が既にオープンされていると思って, 3 から読み込み、 4 に書き出す。

さらに、 Open Mathmatica サーバはコントロールプロセスからシグナルを受け取る場合がある。シグナルを受け取った場合には, 相応の動作が必要であるが、現在は実装していない. SIGUSR1 (SM control reset connection) は計算が全て終わってから OX SYNC BALL を投げるので、実際には意味がない。

3 OX スタックマシン

スタックのオブジェクトは cmo 型の変数、あるいはその派生クラスである. つまり、 Open XM 規約で定められたデータ形式を流用している. この方法の利点は Open XM プロトコルを通して通信するにあたって特にデータの変換を必要としないことである. すなわち CMO の各データタイプは Open Mathematica サーバ (スタックマシン) の内部でも, CMO として保持するわけである.

サーバの各関数は cmo* を受け取り、タグをみて実際のクラスが何であるかを知り、動作を決定する.

4 Mathematica との通信 (MathLink) について

CMO は次のように変換されてから, MathLink を通して送られる.

1. CMO INT32 は MLTKINT (多倍長整数型).

2. CMO STRING は MLTKSTR (文字列型).

3. CMO LIST は MLTKFUNC (関数型).

4. その他のタイプの CMO は ToExpression[文字列] として送る.

上で述べられている ToExpression は Mathematica の組み込み関数であり, 文字列を引数として Mathematica の式を返す. ([4, pp.407])

ここで一つ注意をしておく. MathLink では, int 型以外のデータを MLTKINT として送ることは残念ながらできない. したがって CMO ZZ を直接, 整数型であると Mathematica に思わせることはできないのである. そこで, 次のような方法をとることになる.

char *CONVERT_ZZ_TO_CSTRING(cmo_t zz);
int main()
{
  char *s;
  cmo_t zz;  /* zz.tag == CMO_ZZ */
  MLINK lp;  /* MathLink Socket */
  ...
  s = CONVERT_ZZ_TO_CSTRING(zz);
  MLPutFunction(lp, "ToExpression", 1);
  MLPutString(lp, s);
  ...
}

このようにすると, Mathematica 側では, 例えば

                  ToExpression["1234567890"]

という評価が行われ, 文字列データから整数が復元される.

逆に, Mathematica から送られた整数データは, マシン整数の範囲内であれば, int として取得可能 (MLGetInteger を使う) であるが, 受け取る前に int に収まるか否かを知ることはできない. int に収まらない場合、データが切り捨てられてしまうので注意が必要である. また, 直接 CMO ZZ として取得することも不可能である. (MathLink 上でどのような形式でデータ交換されているのかの情報は手元にある資料からは得られなかった)

しかしながら, たとえ Mathematica 側から整数データが送られていたとしても, そのデータを文字列に変換して受け取ることは MathLink の機構上可能である.

これを利用して, 我々は次のようにして整数を受け取る.

cmo_t CONVERT_CSTRING_TO_ZZ(char *s);
int main()
{
  MLINK lp;
  char *s;
  cmo_t zz;
  ...
  if(MLGetNext(lp) == MLTHINT) {
    MLGetString(lp, &s);
    zz = CONVERT_CSTRING_TO_ZZ(s);  /* zz.tag == CMO_ZZ */
  }
  ...
}

つまり、 Mathematica から整数データを文字列として受け取り、その文字列を OX サーバ側で CMO ZZ に直している。

基本的に MathLink では全てのデータを文字列で受け取るしか方法はない。どのような種類のデータであるかは受け取る前に知ることはできる。データの型は、 MLTKERR(エラー), MLTKINT(整数), MLTKSTR(文字列), MLREAL(実数), MLTKSYM (シンボル), MLTKFUNC(関数) のいずれかである。このような事情で Mathematica から受け取ったデータは基本的に CMO STRING としてスタックに積まれるので、クライアント側でその文字列の解釈をする必要がでてくる。

しかしながら、全ての MathLink オブジェクトが文字列に変換できるわけではないので、その取り扱いには注意を要する。まだ、実装していないが、多項式 (CMO ??? PORINOMIAL) の扱いが難しい。

5 個々のスタックマシン命令の実装

現在、実装されているのは SM popCMO, SM popString, SM pops, SM executeFunction, SM executeStringByLocalParser, SM mathcap, SM setMathcap(受け取るだけで何もしない) である。

6 Mathematica を OX のクライアントに

OpenXM クライアントは Mathematica の外部プログラム (math2ox) の形で実現されている。すなわち、 Mathematica と math2ox の間は MathLink プロトコルで、 math2ox と OpenXM サーバの間は OpenXM プロトコルで通信し、 math2ox が適切に情報を変換しながらやりとりする。その意味で wrapper の一種であるとも言える。

利用するには、最初に

In[1]:= Install["math2ox"]

として、 math2ox をロードしなければならない。 Mathematica に新たに定

義されるコマンドは、 OxStart[s String], OxStartInsecure[s String,
p Integer, q Integer], OxExecuteString[s String], OxParse[s String],
OxGet[], OxPopCMO[], OxPopString[], OxClose[], OxReset[] の 9 つ

である。 math2ox をロードしたら、

In[2] := OxStart["ox_sm1"]

によって OpenXM サーバに接続する。この場合の接続先は ox sm1 である。もちろん

In[2] := OxStartInsecure["water.s.kanazawa-u.ac.jp", 1300, 1400]

のようにして、 insecure モードで接続してもよい。ただしこの場合は、あらかじめ Run[] 等で、 OpenXM サーバを起動しておかなければならない。

接続が成功したらデータを送ってみよう。

In[3] := OxParse["(CMO_LIST, (CMO_STRING, "hello world"), (CMO_ZERO))"]

のように CMO expression を指定することによって、任意の CMO を送信できる。正しくない CMO の場合には、何も送信されない。また、 CMO ではなく、

In[4] := OxParse["(OX_COMMAND, (SM_popCMO))"]

などとして、 OX メッセージの形で記述することもできる。注意しなければならないのは、 SM コマンドの場合、 OX スタックマシンから OX メッセージが送られてくる場合があるが、 OxParse[] を用いた場合、このメッセージは自動的には受信しない (現在の仕様では)。したがって明示的に受信する必要がある。そのためには

In[5] := OxGet[]

とするだけでよい。返ってくるオブジェクトは CMO に対応するものである。

In[6] := OxPopCMO[]

を用いる場合にはもちろん OxGet[] を呼び出す必要はない。

計算を実行するには OxExecute[] (SM executeStringByLocalParser) か、適切な OX メッセージを送信すること。

計算が終わったら、

In[7] := OxClose[]

とすると、接続が終了する。

A 付録

GMP における “整数型” mpz t はつぎのような内部表現を持つ:

まず mpz t 型は
typedef struct __mpz_struct mpz_t[1];

と typedef されており, mpz t 型の変数は (関数の仮引数でない限り) 配列の扱いである. また,

typedef unsigned long int mp_limb_t;

と宣言されている場合には, 変数 mpz t x の x-> mp d が unsigned long int の配列であり, データの実体である. これは整数の最下位 4 バイトが配列の先頭にくる. つまり全体としては “リトルエンディアンっぽい” が, 各 unsigned long int はマシンのネイティブな integer である. つまり, GMP の内部表現はマシン依存となっている.

参考文献

[1] 野呂正行, 高山信毅. Open XM の設計と実装 — Open message eXchange protocol for Mathematics, 1999/11/22 [2] 小原功任, 高山信毅, 野呂正行. Open asir 入門, 1999, 数式処理, Vol 7,

No 2, 2–17. (ISBN4-87243-086-7, SEG 出版, Tokyo).

[3] ウルフラム. Mathematica (日本語版), アジソンウエスレイ, 1992.

[4] Stephen Wolfram. The Mathematica Book, Third edition, Wolfram Media/Cambridge University Press, 1996.

[5] 宮地力. Mathematica によるネットワークプログラミング, 岩波コンピュータサイエンス, 岩波書店, 1998.