SB-Prologを使う
%% これは、筆者が
技術評論社 刊 ソフトウェアデザイン誌
「つこてなんぼのFreeBSD」
1998年11月
に掲載した原稿をもとにしたものです %%
0. はじめに
Lispと同じくPorlogも人工知能用の言語として、1980年代には大いに利用さ
れました。
Prologは1980年代に産まれた新しい言語で、計算の原理が推論に基づいて
います。つまり、Prologのプログラムは一階述語論理の論理式で記述し、計算
の実行は、その論理式を論理推論することと同じです。
人間(ソクラテス). % ソクラテスは人間である
死ぬ者(X) :- 人間(X). % 人間であるような X ならば 死ぬ
を知識データベースに入れ、
?- 死ぬ者(ソクラテス).
という問い合わせを発行すると、ソクラテスは死ぬという結論が得られます。
ここでは、
ソクラテスは人間である。
人間なら死ぬ。
よって、ソクラテスは死ぬ。
という三段論法を一回実行していることになります。
そこで、Prologは知識情報処理のできる、高級言語であるといわれています。
実際には、Prolog処理系は、それを逆向きに推論します。よって、Prologを
プログラミング言語として見た場合に、実行をサブルーチンの呼び出しとして
見れば、
死ぬ者 -> 人間
という順序で、通常のプログラミング言語と違和感なく使用できます。
Prologは、通産省の、第5世代コンピュータ(知識処理を行うとされた)開発計
画の中核言語にもなり、日本は世界でも有数のProlog使用国です。
Prologは、研究用に作られた処理系がたくさん有り、産まれが新しいので、
フリーに配られているものも多くありました。
しかし、最近ではどのProlog処理系も開発が止まっており、 Intel系のUNIX
ですぐに動く処理系はほとんどありません。
今回紹介するSB-Prologは現在でも簡単に動かせる処理系です。
なお、今回使用したOSはFreeBSD2.2.2とFreeBSD2.2.5です。
1. SB-Prolog
SB-PrologはStony BrookにあるSUNYのDavid WarrenとSuzanne Dietrichによっ
て作られ、メンテナンスがアリゾナ大学に移って、現在に至ります。とはいえ、
1987年以来まったく変化がありません。
SB-Prologの作者であるDavid Warrenは、Prologを効率よく実行するためには、
こういうアーキテクチャのコンピュータがあればよい、という、
「Warrenの抽象機械(Warren's Abstract Machine=WAM)」
を考案した人です。
WAMは最初はPrologコンパイラのために考えられたのですが、WAMは Prolog実
行の本質をついていたので、WAM以降、Prologマシンのアーキテクチャは強く
WAMの影響を受けます。
日本で第5世代計算機を研究していたICOTのPrologマシンも、WAM以降はWAMを
モディファイしたものになっていきます。
SB-PrologはそのWarrenが作った処理系なので興味深いものがあります。
SB-Prologには、コンパイラもありますが、そのオブジェクトは、WAMをター
ゲットとしたものになっています。
そして、SB-Prologの実行系は、実は、WAMのインタープリタです。
つまり、CでWAMの仮想マシン・インタープリタを記述し、実行はWAMインター
プリタが行います。
また、SB-Prologでは、そのほとんどの機能がPrologで記述してあります。
SB-Prologでは、Prologのコンパイルがネイティブな機械語でなく、WAMへの
コンパイルなので、実行速度に不満はあります。とはいえ、前回のGCL(KCl)と
同様、ネイティブ・コードへのコンパイリングでないおかげで、この時代でも
簡単に使用できるのです。
普通のスペックのPrologが、手軽に使えるのですから、多少のオーバヘッド
は我慢するしかないでしょう。
なお、SB-PrologはPrologの標準的な文法であるDEC10 Prologに準拠していま
す。
有名なC-PrologやQuintus-Prologともほぼコンパチブルです。
2.コンパイル
SB-Prologは
ftp://ftp.cs.arizona.edu/sbprolog/v3/
よりgetします。
最新というよりは、最終版である、Ver3.1が得られます。
makeはsim/で行います。
simはWAMのシミュレータ(仮想マシン・インタープリタ)です。
最近のUNIXでSB-Prologを使用するには、アーカイブを展開した後、
sim/Makefileを
Makefile.patch
のように変更します。
この後、
% cd sim
% make
すると、simとbuiltinがmakeされ、sim/sbprologができあがります。
3. SB-Prologの動かし方
sim/sbprologが実行ファイルです。しかし、これは仮想マシンだけで、ユーザ
と対話する機能などは入ってません。
そこで、sbprologの引数として、仮想マシンが実行すべきプログラムを指定し
てやります。
通常は、そこで指定するプログラムにユーザと対話するためのトップレベルを
指定します。
また、標準的なPrologに組み込みの述語も外部ファイルとなっているので、そ
れらのサーチパスを環境変数SIMPATHに指定しておきます。最低限、SB-Prologが
標準で持っているライブラリ(cmplib, modlib, lib)を設定しなければ、Prolog
処理系として実用的ではありません。SIMPATHには複数のディレクトリを':'で区
切って指定できます。
ここでは、SB-Prologを、/src/sbprologV3に展開してあるとします。
% setenv SIMPATH /src/sbprologV3/cmplib:/src/sbprologV3/modlib:/src/sbprologV3/lib:.
% sbprolog '/src/sbprologV3/modlib/$readloop'
SB-Prolog Version 3.1
| ?-
となれば、正常に起動しています。
「| ?-」はプロンプトです。
節の定義は対話的にも可能ですが、非常に繁雑なので、プログラム・ファイル
をロードするのが簡単です。
エディタで次の様なファイル
append.prolog
を作成します。
--- append.prolog
%% Append
append([],X,X).
append([A|X],Y,[A|Z]):- append(X,Y,Z).
--- ここまで
では、SB-Prologにロードしましょう。
| ?- consult('append.prolog').
yes
| ?-
となります。
さて、appendを実行します。
| ?- append([a,b,c], [x,y,z], X).
X = [a,b,c,x,y,z] ここで一旦停止するので、「return」を入力
yes
| ?-
と、2つのリスト[a,b,c]と[x,y,z]がつながれています。
通常のプログラミング言語ならこれでおしまいですが、Prologの高級さは、こ
れだけではありません。
| ?- append(X,Y,[a,b,c,d]).
X = []
Y = [a,b,c,d]; ここで一旦停止するので、「;」「return」を入力
X = [a]
Y = [b,c,d];
X = [a,b]
Y = [c,d];
X = [a,b,c]
Y = [d];
X = [a,b,c,d]
Y = [];
no
| ?-
このように、答を入れると問題が出るという、はなれ技。
Prologの実行はあくまで論理式の正しさに依っているので、双方向の実行が可
能なのです。
途中の入力は、「;」を入力すると、ORを意味し、別な解を求めに行きます。もうそれ以上の解答が必要ない場合は、単に「return」を入力して探索を打ち切ります。
DEC10 prolog系では、変数は大文字で記述し、定数は小文字で記述します。
また、
append([A|X],Y,[A|Z]):- append(X,Y,Z).
で使用している、[A|X]は、リストのcarとcdrを分解してパターンマッチさせる
記述で、この場合、変数Aにリストのcarが変数Xにcdrがマッチしてバインドされ
ます。
さて、ソクラテスの例もできます。
socrates.prolog
(SB-Prologは漢字は使えないので英語です)
--- socrates.prolog
human(socrates).
mortal(X) :- human(X).
---ここまで
実行は
| ?- consult('socrates.prolog').
yes
| ?- mortal(socrates).
yes
ということで、ソクラテスは死ぬことが判ります。:-)
また、算術演算もできます。
fact.prolog
--- fact.prolog
%% fact
fa(0,1) .
fa(N,X) :- N1 is N -1 , fa(N1,X1),X is X1 * N .
---ここまで
実行は
| ?- consult('fact.prolog').
yes
| ?- fact(6,X).
X = 720
yes
ということで、階乗も計算できます。
isは単一方向の代入であり、
N1 is N-1
は、 Cで書く
N1=N-1;
と同じ意味です。
また、算術四則演算子は中置き記述が可能です。
コンパイルも可能です。
complie(ソースファイル名 , オブジェクト・ファイル名)
とします。
一度、インタープリタで定義を行ったものは、コンパイル後は、loadしなけれ
ばなりません。
| ?- compile('append.prolog', 'append').
Compile : append.prolog => append
compilation complete -- 0.11 secs
yes
| ?- load('append').
yes
| ?- append(X,Y,[a,b,c,d]).
X = []
Y = [a,b,c,d];
(以下略)
SB-Prologは、内部でみつからなかった述語については、SIMPATHに従って、自
動的に機械語ファイルをサーチし、ロードします。
よって、自動的にロードして欲しい述語は、そのファイル名と述語名を一致さ
せておかねばなりません。そうしておけば、自分で定義しコンパイルした述語が、
自動的にロードされ、非常に便利です。
SIMPATHにカレント・ディレクトリ(.)を入れておけば、コンパイルして、即座
に述語として自動ロードさせることができます。
4. より便利に
より便利にSB-Prologを使用するために、
setenv SIMPATH /src/sbprologV3/cmplib:/src/sbprologV3/modlib:/src/sbprologV3/lib:.
は、.cshrcなどに記述しておくべきでしょう。
また、/usr/local/bin/prologなどとして、
次のようなshellスクリプトを用意すると便利です。
--- /usr/local/bin/prolog
#!/bin/sh
/src/sbprologV3/sim/sbprolog /src/sbprologV3/modlib/\$readloop
---
emacs(mule)からprologを起動すると非常に便利です。
emacsに標準のprolog.elは、元富士通研究所の梅田さんが書かれたものなので
すが、C-PrologとQuintus Prolog用のもので、SB-PrologにはLisp変数の初期値
が不適当です。
そこで、.emacsなどに
---
(setq prolog-consult-string "consult(user).\n")
(setq prolog-eof-string nil)
---
と記述します。
そしてmuleを起動したのち、M-x run-prologとして、prologを起動します。
その後、M-x 2 で窓を2つに分割し、片方でソースを編集すると非常に便利です。
そして、ソースを編集している窓から、簡単なキー操作で、Prolog処理系へソー
スを読み込ませることができます。
その方法は、
- 送り込みたい節の頭でマーキング(C-space)を行う
- 送り込みたい部分の最後にカーソルを移動
- M-C-x (ESC,C-x)を押下
すると、指定したリージョンが自動的にconsultされます。
これで、もう、Prologマシンは不用になりましたね。:-)
emacsのprologモードでは、インデントを自動的につけてくれます。
Prologのコメントは「%」で開始した行です。
emacsのprologモードの場合、%%がパラグラフの開始で、%は通常のコメントです。
5. マニュアルの見方
SB-Prologにはsbprolog_doc.meという、非常に詳しいマニュアル・ファイルが
あるので、それを読めばすべてわかります。
ただし、テーブルなどが入ったroffファイルなので、それをキャラクタ端末で
読むには、
% tbl sbprolog_doc.me |nroff -me |col
としなければなりません。
こうすれば、lessなどで読める形になり、オンラインで検索できるので、非常
に便利になります。
--- EOF
たけおか(竹岡尚三)のPrologページ 目次