[BACK]Return to ox_math.tex CVS log [TXT][DIR] Up to [local] / OpenXM / src / ox_math / documents

File: [local] / OpenXM / src / ox_math / documents / ox_math.tex (download)

Revision 1.8, Tue Jul 19 15:58:37 2005 UTC (18 years, 11 months ago) by ohara
Branch: MAIN
Changes since 1.7: +140 -14 lines

revised

%#!platex
%% $OpenXM: OpenXM/src/ox_math/documents/ox_math.tex,v 1.8 2005/07/19 15:58:37 ohara Exp $

\documentclass{jarticle}
\title{Mathematica の Open XM 化について
% \\ {\small --- Open Mathematica サーバの内部構成 ---}
}
%\date{January 19, 1999}
%\date{July 12, 1999}
\date{November 25, 1999\\
(Revised July 20, 2005)
}
\author{小原功任}

\def\oxmath{{\tt ox\_math}}

\begin{document}
\maketitle

\noindent
{\bf 
注意 (2002.04.17):
この文書は, 古いインタフェースをもとに記述してあるので,
例はこのままでは動作しないので注意.
math2ox.texi が最新のインタフェースのマニュアルである.
一番の変更点は, {\tt OxStart} が pid (ox process id) を戻すようになり,
{\tt OxParse} など多くの関数が, pid を引数として求めるようになったことで
ある.
たとえば, この文書の {\tt OxParse} を用いる例は, 次のように変更しないと
いけない.}
\begin{verbatim}
Install["math2ox"]
pid = OxStart["ox_sm1"]
OxParse[pid,"(CMO_ZERO)"]
OxPopCMO[pid]
\end{verbatim}


\section{我々が提供するもの}

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

動作環境は Solaris, Linux および Windows、対象としている Mathematica の
バージョンは、3.0 〜 4.2 までである。バージョン 5.x については、我々が所
有していないため調査していない。

Windows 上では \oxmath は、cygwin のもとで動作する。\oxmath の Windows 
対応は藤本さんによる(2002年4月)。ありがとう。

\section{Open Mathematica サーバの構成}

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

さらに \oxmath には計算中断機能が必要であるが、この機能は 2003年のはじめに実装された。

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

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

\section{MathLink プログラミングの基礎知識}

ここでは、MathLink についての基礎的事項を説明する。概ね、Mathematica
Book~\cite{Wolfram-1996} や宮地~\cite{miyachi-1998} などを参照すればよい
が、必ずしもこれらの書籍に明確に書かれているわけではない(探せば見つかる
が)。

まず MathLink とは、Wolfram が提供するライブラリであり、Mathematica のネッ
トワーク対応部分に相当する。Mathematica Kernel と通信するプログラムを書
こうとするならば、MathLink を利用する必要がある。MathLink の内部構成は明
らかにされていないが、{\bf 大部分はネットワーク透過的}である(例外はある)。

まず、MathLink の通信路で交換されるデータが何なのか、ということを理解す
る必要がある。答は{\bf Mathematicaの式}である。これは自明ではない。
次のような式がその例である。
\begin{verbatim}
    EvaluatePacket[Sin[\$VersionNumber]]
    ReturnPacket[Sin[x]]
    InputNamePacket["In[1]:= "]
    MenuPacket[1,"Interrupt> "]
\end{verbatim}
このような *Packet[] を \cite{Wolfram-1996}ではパケットと呼んでいる.
MathLink を用いて、確実なプログラミングをするためには、これらのパケット
を正しく扱う必要がある。

さて、Mathematica Kernel の起動および通信路の確立については省略する。
いったん、通信路が確立されたら、
\begin{enumerate}
\item Mathematica Kernel に式を送る。
\item Mathematica Kernel から式を受け取る。
\end{enumerate}
を繰り返すのが MathLink でのプログラミングである。

\oxmath は Mathematica と以下のような意味で{\bf 文字列ベース}で通信して
いる。まず Mathematica Kernel に評価させたい式が、C 言語の文字列で与えら
れているとして、link で指し示すMathematica Kernel に
\begin{verbatim}
int ml_evaluateStringByLocalParser(char *str)
{
    MLPutFunction(link, "EvaluatePacket", 1);
    MLPutFunction(link, "ToExpression", 1);
    MLPutString(link, str);
    MLEndPacket(link);
}
\end{verbatim}
として送信する。パケットは、
EvaluatePacket[ToExpression[{\it str}]] である。

評価された結果を配列 str に格納するには、単純には次のようになる。
\begin{verbatim}
int receive_sample(char str[])
{
    while (MLNextPacket(link) != RETURNPKT) 
        MLNewPacket(link);
    switch(MLGetNext(link)) {
    MLTKSTR:
        MLGetString(link, &str);
        ...
    MLTKINT:
        ...
    }
    MLNewPacket(link);
}
\end{verbatim}
この例では ReturnPacket[] 以外を無視しているが、実際にはこんなに単純には
書けない。\oxmath の実装では、mlo.c の
ml\_next\_packet(), ml\_new\_packet(), ml\_read\_packet(), 
ml\_read\_returnpacket(), ml\_read\_menupacket(), ml\_read\_textpacket()
などを見てほしい。

\section{Mathematica との通信(MathLink) について}

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

\begin{enumerate}
\item CMO\_INT32 は MLTKINT (多倍長整数型).
\item CMO\_STRING は MLTKSTR (文字列型).
\item CMO\_LIST は MLTKFUNC (関数型).
\item その他のタイプの CMO は ToExpression[文字列] として送る.
\end{enumerate}

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

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

\begin{verbatim}
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);
  ...
}
\end{verbatim}

このようにすると, Mathematica 側では, 例えば
\[
\mbox{\tt ToExpression["1234567890"]}
\]
という評価が行われ, 文字列データから整数が復元される.

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

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

これを利用して, 我々は次のようにして整数を受け取る.
\begin{verbatim}
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 */
  }
  ...
}		
\end{verbatim}

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

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

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

\section{個々のスタックマシン命令の実装}

現在、実装されているのは
SM\_popCMO, SM\_popString, SM\_pops, SM\_executeFunction,
SM\_executeStringByLocalParser, SM\_mathcap, SM\_setMathcap(受け取るだけ
で何もしない)である。

\section{\oxmath への計算中断機能の実装}

\noindent
{\bf 注意: {\tt ox\_math\_interruption.tex} 
に Risa/Asir Conference (2003) での講演原稿がある.}

OpenXM プロトコルは、エンジンに対して、計算中断機能を要求する。\oxmath 
のような wrapper プログラムでは、そのような機能を実装するのは一般には難
しいが、MathLink には Mathematica Book~\cite{Wolfram-1996} に書かれてい
ない機能があり(\cite{MathSource-Google1}, \cite{MathSource-Google2},
\cite{Math-Output1})、そのひとつを用いて、\oxmath に計算中断機能を実装し
た。この節では、その実装について説明する。

Mathematica Kernel に対する割り込みは、
\begin{enumerate}
\item MLPutMessage で Mathematica Kernel に MLInterruptMessage を送る。
\item 通信路の後始末を行い、最終的に ReturnPacket[\$Aborted] を受け取る。
\end{enumerate}
ことでなされる。
MLPutMessage は MathLink の非公開関数でネットワーク透過性はない。
Unix と Windows では異なるが、Unix の場合、MLInterruptMessage の実体は
SIGINT である。
通信路の後始末には、{\bf Mathematica Kernel のバージョン依存性がある}ので、
それを回避すると、結局、次の手順になる。
\begin{enumerate}
\item MLPutMessage(link, MLInterruptMessage) 
\item MenuPacket[1,"Interrupt> "] を受け取れば計算が中断されている
\item MLPutString(link, "$\backslash$n")
\item MenuPacket[0,"Interrupt> "] を受け取る
\item MLPutString(link, "a")
\item TextPacket["..."] を受け取る
\item EvaluatePacket[0] を送って、ReturnPacket[...] をふたつ受け取る。
最初のものが ReturnPacket[\$Aborted] である。
\end{enumerate}

最後の手順を説明する。
ここで、ReturnPacket[\$Aborted] が素直に返ってくればいいのであるが、
バージョン 3.x では返ってくるのに、バージョン4.xでは、何故か、
返ってこず、次の計算を行うとき、ふたつまとめて返ってくる。
よって、ダミーにEvaluatePacket[0] を送るのである。

\section{Mathematica を OX のクライアントに}

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

利用するには、最初に
\begin{verbatim}
In[1]:= Install["math2ox"]
\end{verbatim}
として、math2ox をロードしなければならない。
Mathematica に新たに定義されるコマンドは、
{\tt OxStart[s\_String], OxStartInsecure[s\_String, p\_Integer, q\_Integer],
OxExecuteString[s\_String], OxParse[s\_String], OxGet[],
OxPopCMO[], OxPopString[], OxClose[], OxReset[]}
の9つである。

math2ox をロードしたら、
\begin{verbatim}
In[2] := OxStart["ox_sm1"]
\end{verbatim}
によって OpenXM サーバに接続する。この場合の接続先は ox\_sm1 である。
もちろん 
\begin{verbatim}
In[2] := OxStartInsecure["water.s.kanazawa-u.ac.jp", 1300, 1400]
\end{verbatim}
のようにして、insecure モードで接続してもよい。ただしこの場合は、
あらかじめ {\tt Run[]} 等で、OpenXM サーバを起動しておかなければならない。

接続が成功したらデータを送ってみよう。
\begin{verbatim}
In[3] := OxParse["(CMO_LIST, (CMO_STRING, "hello world"), (CMO_ZERO))"]
\end{verbatim}
のように CMO expression を指定することによって、
任意の CMO を送信できる。
正しくない CMO の場合には、何も送信されない。
また、CMO ではなく、
\begin{verbatim}
In[4] := OxParse["(OX_COMMAND, (SM_popCMO))"]
\end{verbatim}
などとして、OX メッセージの形で記述することもできる。
注意しなければならないのは、SM コマンドの場合、OX スタックマシンから
OX メッセージが送られてくる場合があるが、OxParse[] を用いた場合、
このメッセージは自動的には受信しない(現在の仕様では)。したがって明示的に
受信する必要がある。そのためには
\begin{verbatim}
In[5] := OxGet[]
\end{verbatim}
とするだけでよい。返ってくるオブジェクトは CMO に対応するものである。
\begin{verbatim}
In[6] := OxPopCMO[]
\end{verbatim}
を用いる場合にはもちろん {\tt OxGet[]} を呼び出す必要はない。

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

計算が終わったら、
\begin{verbatim}
In[7] := OxClose[]
\end{verbatim}
とすると、接続が終了する。

\appendix
\section{付録}

GMP における ``整数型'' {\tt mpz\_t} はつぎのような
内部表現を持つ: \\
まず  {\tt mpz\_t} 型は
\begin{verbatim}
typedef struct __mpz_struct mpz_t[1];
\end{verbatim}
と typedef されており, 
{\tt mpz\_t} 型の変数は(関数の仮引数でない限り)配列の
扱いである. また, 
\begin{verbatim}
typedef unsigned long int mp_limb_t;		
\end{verbatim}
と宣言されている場合には,
変数 {\tt mpz\_t x} の {\tt x->\_mp\_d} が unsigned long int の
配列であり, データの実体である.
これは整数の最下位4バイトが配列の先頭にくる.
つまり全体としては``リトルエンディアンっぽい''が, 
各 unsigned long int はマシンのネイティブな integer である.
つまり, GMP の内部表現はマシン依存となっている.

\begin{thebibliography}{99}
\bibitem{Openxxx-1998}
野呂正行, 高山信毅.
{Open XM の設計と実装 --- Open message eXchange protocol for Mathematics},
November 22, 1999, Revised March 4, 2005.
\bibitem{Ohara-Takayama-Noro-1999}
小原功任, 高山信毅, 野呂正行.
{Open asir 入門}, 1999, 数式処理, Vol 7, No 2, 2--17. (ISBN4-87243-086-7, SEG 出版, Tokyo).
\bibitem{Wolfram-1992}
ウルフラム.
{Mathematica (日本語版)},
アジソンウエスレイ, 1992.
\bibitem{Wolfram-1996}
Stephen Wolfram.
{The Mathematica Book}, Third edition,
Wolfram Media/Cambridge University Press, 1996.
\bibitem{miyachi-1998}
宮地力.
{Mathematica によるネットワークプログラミング},
岩波コンピュータサイエンス,
岩波書店, 1998.
\bibitem{MathSource-Google1}
Todd Gayley.
[mg17015] in MathArchive,
1999 April.
\bibitem{MathSource-Google2}
昔の MathLink にあった MLSignal の解説.
(以前、Google のキャッシュにあったが、もうない)
\bibitem{Math-Output1}
mathlink.h, libMLa のシンボル表, mprep の生成するソース.
\end{thebibliography}

\end{document}