prolog(2)

花は桜木、人は武士

武士は兎も角として、桜程、日本人に愛される花は無いだろう。桜の木の下での花見。 一年で一番幸せな時だ。日本流のピクニックと言ってしまったら風情が無いか。

酒を飲んでくだを巻いていても、一年で一度の事だから。。。 そういう事情を知ってか知らずか、地元の蔵がオープンされるんだ。試飲のグラスを買って 中に入ると、19種のフレーバーが待っている。丁寧に試飲してくと、それだけで酔えるぞ。

蔵の人の話では、フレーバーを決定付ける要因はいろいろあるとの事だけど、一番は使う 麹によるとか。蔵秘伝で、色々な種類の麹を混合して使うそうだ。酒呑みのくせに、そういう 奥深い事を知らないんじゃ話しにならんな。今度(密)造酒の作り方なんて本を読んで みようかな。

酒が飲めない人には、甘酒サービス。お母さん方には、酒粕詰め放題の余興。皆さん髪を 振り乱して、、、じゃなくて、隣の人達と和気藹々におしゃべりしながら、詰めてます。

女房もつかみ取りに参戦。おいらは後ろから応援。隣に座ったおばちゃんが言う事にゃ、 板状の酒粕をそのまま詰めたんじゃ、隙間が出来て細密充填にはならないよとの事。粕を 一度手の中で丸めて柔らかくし、それを袋に詰めていけば、粘土のごとくぴったりと したものが出来るとか。生活の知恵ですなあ。

酒粕で出来るレシピが有ったので頂いてきた。cookpadを見てもいいけど、田舎流って事で。

酒粕クラッカー
1.薄力粉(100g)、酒粕(20g)、油(大さじ2)、塩(小さじ1/2)、水(大さじ1)、
酢(小さじ2)。
2.ボールに薄力粉、酒粕、油、塩を入れて、さっくりと混ぜ、そぼろ状にする
3.水、酢を加えて軽く混ぜたら、こねずにひとつにまとめ、5mmの厚さに延ばしてから、1cmの幅に切り分け
4.160度の余熱したオーブンで10分焼くと出来上がり
焼き酒粕
1.板状酒粕(100g)、黒砂糖(少々)
2.細かく刻んだ黒砂糖を酒粕の上に散らす
3.黒砂糖の上に細かく刻んだ粕を散らす
4.オーブンで5分程焼く
5.黒砂糖が溶けたら、出来上がり

この他にも、板粕をゆっくり炙って食べる、シンプルな(しかも一番旨い)食べ方等 が、紹介されてた。酒粕の賞味期限は約3月。冷蔵庫か冷凍庫に保管との事です。

prologの解せない点

例の7つの言語本を読んでいると、prologの自慢もとえ特徴がappendを使って、説明されてる。 appendってリストの結合ね。schemeのコードで言うとこんなの。

(define (append x y)
  (if (null? x)
      y
      (cons (car x) (append (cdr x) y))))

pure語で言うと

 [] + ys = ys;
 (x:xs) + ys = x : xs+ys;

まあ、似たような構造だわな。いずれも、アリティーが2になってる。所が所が、prolog語だと、 アリティーが3なのよ。prolog風な表し方だと、append/3 って事になる。コードはどう なってるかと、swiplのlibrary/list.plから引っ張ってくると、

%%      append(?List1, ?List2, ?List1AndList2)
%
%       List1AndList2 is the concatenation of List1 and List2

append([], L, L).
append([H|T], L, [H|R]) :-
        append(T, L, R).

pure語に近いけど、第3の引数を内包してる所が、おいらにとっちゃ奇異に思えるのさ。 全ての関数(述語が正しいのかな)が、出力端子を内包してるかと思うと

| ?- X is cos(pi).

X = -1.0

yes
| ?- sin(pi).
uncaught exception: error(existence_error(procedure,sin/1),top_level/0)

こんな具合に使い分けしないとならない。数値の演算は可逆性が無いからかな? 若し、md5なんていう message digestを計算する関数が可逆なら、インターネットの世界が成り立たなくなるものなあ。 まあ、そういう事だろうね。そういう事にしておこう。

で、append/3だけど、4つの効能があるという。

?- append([a,b], [c,d], [a,b,c,d]).
true.

?- append([a,b], [c,d], [a,z,c,d]).
false.

これを称して、嘘発見器と言うそうな。

?- append([a,b], [c,d], What).
What = [a, b, c, d].

リストの作成。scheme界とかだとこれしか使い道が無い。

?- append([a,b], X, [a,b,c,d]).
X = [c, d].

リストの差分だそうですが、ちょっと誤解を招くかな?

?- append(X, Y, [a,b,c,d]).
X = [],
Y = [a, b, c, d] ;
X = [a],
Y = [b, c, d] ;
X = [a, b],
Y = [c, d] ;
X = [a, b, c],
Y = [d] ;
X = [a, b, c, d],
Y = [] ;
false.

リストを分解する方法を洗い出すんですって。まさにprologは他の言語とは一線を課しているなあ。

ああ、おいらが新鮮に感じたのにもう一つあった。atomってやつ。文字列ちゃうで! Schemeあたりで言うシンボルが、atom相当で、どこにも自在に登場する点。

困っちゃうなあ

サザエさんの旦那さんは益男さん。表明を書くと

married(sazae, masuo).

こんな風に2人は夫婦ですってなります。ああ、最近、笹川良一の伝を読んだんだけど、 何人も夫婦同様の人が居たとか。こういう羨ましい人の事は取り合えず考えません。 で、実に下らない質問。

| ?- married(sazae, Who).

Who = masuo

yes
| ?- married(masuo, Who).

no

最初の質問は当たり前の結果だけど、2番目の質問はどうよ? 世間一般の常識から外れれて いるぞ。そなら、そういうのにも対応出来るように

married(X,Y) :- married(Y,X).

これでどうだ。

| ?- married(masuo, Who).
^C
Prolog interruption (h for help) ? h
   a  abort        b  break
   c  continue     e  exit
   d  debug        t  trace
  h/? help

Prolog interruption (h for help) ? d
The debugger will first leap -- showing spypoints (debug)

Fatal Error: local stack overflow (size: 16384 Kb, reached: 16384 Kb, environment variable used: LOCALSZ)

質問した所、いつまでたっても答えが返ってきません。Ctrl-Cして、debuggerに 入ろうとした所、落ちちゃいました。変な質問はしないように!

swipl on rpm

今の所、FreeBSDにgprologが入っているんで、Fedoraには違う物をいれようと思っていたんだ。 そしたら、何故 いまどき Prolog in 2008 ページに出会ったよ。お歳を召した方が楽しんでおられる。 面白そうなので、おいらも swi prologをチョイスしてみた。

Fedoraのパッケージシステムから入れると古いのが入ってしまうので、 SWI-Prolog on Redhat (Fedora, RHEL, CentOS) 経由で、下記の物を取り寄せ。

[sakae@fedora ~]$ ls -U pl*
pl-6.6.1-1.fc21.i686.rpm      pl-xpce-6.6.1-1.fc21.i686.rpm
pl-doc-6.6.1-1.fc21.i686.rpm

rpm -i を思い出したように使って入れたよ。まだ、ボケてはいないな。えっ? ソースから って言う流儀はどうした? swiplを使う醍醐味は、xpceって言うグラフィックでしょう。 そんなのをちまちまとコンパイルしてたら、日が暮れてしまいますよ。

[sakae@fedora ~]$ swipl
Welcome to SWI-Prolog (Multi-threaded, 32 bits, Version 6.6.1)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- emacs.

xpceの元で動くemacsを起動するのが吉。(要、X環境ですけど)枠の雰囲気がちょっと違う emacsが上がってくる。メニューからxpceのデモでも選んで、楽しめば良い。但し、emacsは もどきなんで、elispを駆使して何かしようとしても出来ません。elispが動かないのにemacsとは、 どっかから文句が来ませんかね? 商票侵害ってRMSが言うか。

[sakae@fedora demo]$ wc *pl
   787   5175  32330 chess.pl
   161    767   5546 colour.pl
    76    499   3008 constraint.pl
    43    231   1703 cursor.pl
    62    274   2168 event_hierarchy.pl
   135    500   4211 fontviewer.pl
   413   2746  16325 ftplog.pl
   183    576   4961 graph.pl
   174    728   5215 hsvcolour.pl
   236    703   6709 imageviewer.pl
   670   4025  23393 ispell.pl
   119    413   3488 juggler.pl
   106    546   3807 kangaroo.pl
   221    662   6217 pce_demo.pl
  3386  17845 119081 total
[sakae@fedora demo]$ pwd
/usr/lib/swipl-6.6.1/xpce/prolog/demo

資料には事欠かないぞ。そして、上に上げた、困っちゃうなあは gprologでの挙動だったのだけど、 swiplでやってみると、

?- married(masuo,Who).
Who = sazae ;
Who = sazae ;
Who = sazae

益男さんは、どうやらサザエさんに首ったけのようです。変な質問をする事で、システムが 落ちるという事は無いようです。でも、このストーカーまがいの挙動はどうよ。

そしてhelp系も充実。補完も使えるぞ。

?- apropos(cos).
cos/1                         Cosine
acos/1                        Inverse (arc) cosine
cosh/1                        Hyperbolic cosine
acosh/1                       Inverse hyperbolic cosine
true.

?- cos(pi,V).
V = -1.0.

マニュアルではcosのアリティーが1なのに、アリティー2も受け付けてくれる。これって、 swiplの独自拡張? まあ、便利は良い事なんだけど、ロックインされちゃうなあ。

YAP

先輩のページに紹介されたのを、コレクションしてみる。 YAProlog。YAPって、ヤー・プロログ君って事かと思ったら、 Yet Another Prologって事なのね。rubyのあの人も YARVなんて名前のVMを作っていたから、 何か抜きん出た特徴が有るに違いない。

だって、 もう古の言語だと言うのに、大学で研究して成果を公表してるんだから。 暇にまかせて、能書きを読んでみよう。

マニュアルをちょい見したら、DBとの連携に熱が入っているようだ。バックエンドにDBが 使えるなら、きっとmd5の可逆も涼しい顔をして、こなしてくれるに違いない。

嗚呼、そういう目的なら、自前でデータを用意せずとも、ぐぐるさんに裏でこっそり聞きに 行く道を用意しとけばいいのか。yapでは無いけれど、卒業研究で、面白い事をやってる人が居た。 Prologを用いた大規模データ検索言語 Verno-SPの実装と評価

JIProlog and Prolog Cafe

Java Internet Prolog

こちらは、この所Javaの出番が無かったので、Javaが泣いてると思って入れてみた。 人によっては、Javaはウィルスの住処と言うけど、まあ、Javaバージョンアップした時の 検証用って事で。

こちらは個人使用は無料だけど、ちゃんと使う時は買ってねって事なんで、注意ね。 まあ、おいらには、関係無い制限だけどね。

余りJavaにつれなくするのもアレなんで、日本人による日本人の為のJavaによるprologを 上げておきます。

Prolog Cafe: A Prolog to Java Translator System

AZ-Prolog

まだまだ、コレクションは続きます。何せ骨董的な言語ですからね。

日本人に超お勧めなやつです。 AZ-Prolog 何故日本人にお勧めか? 日本語がスクリプトの中で使えるってのがあるけど、おいらは、 AZ-Prolog ユーザーズマニュアルが、日本語で 読めるってのを挙げたい。

残念ながら上記Webページのコード掲載は禁止されてるんで載せないけど(ついでにと言うか、 一番大事な事だけど、商用利用には購入が必要)、おいらの気に入った コースは、サンプルの中の基本的なリスト処理を経由してLispの実装コースかな。 嗚呼、Prologはリスト処理だけじゃなくて、タプルも使えるのね。

Prolog探索のお勧めコースはもう一つあって、ユーザーマニュアル中の拡張機能パッケージの説明に有る、制約論理。 Prologの特徴が良く出ていると思うぞ。そしてそれを堪能したら、IBM方面へ足を延ばして みれば良い。 ILOGの最適化ソリューション 制約プログラミング が、現実問題を要領よく解く鍵になるだろう。

このAZPrologはWindowsとウブで走るとの事。ウブなんて持ってないので、等価なDebian7で 動くか実験してみた。

sakae@debian7:/usr/local$ ldd /usr/local/bin/prolog
        linux-gate.so.1 (0xb77c0000)
        libazp.so.1 => /usr/local/lib/libazp.so.1 (0xb7604000)
        libdl.so.2 => /lib/i386-linux-gnu/i686/cmov/libdl.so.2 (0xb75ff000)
        libncursesw.so.5 => /lib/i386-linux-gnu/libncursesw.so.5 (0xb75cb000)
        libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb75ab000)
        libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb73fc000)
        libm.so.6 => /lib/i386-linux-gnu/i686/cmov/libm.so.6 (0xb73b9000)
        /lib/ld-linux.so.2 (0xb77c1000)

特殊な物は使っていないようなので、走りそう。

sakae@debian7:~$ prolog
AZ-Prolog Version 7.53 (Linux/x86)

Copyright (C) SOFNEC CO., LTD. 1987-2014/03/12
%% バックスペース(Ctrl-H)を2回押して、一行登録モードにする。
| like(sa, debian-7).

| ?- like(sa,OS).

OS      = debian-7

yes

ちゃんと走ってくれたぞ。何行もコードを書く場合、dlib_require(azedit) して、拡張機能を 取り込み、やおら edit. すれば良い。emacs似のエディターが使えるぞ。

コンパイラーも有ると言うので、試運転してみた。

sakae@debian7:~/src/pl$ azpc -p like.pl
AZ-Prolog Compiler version 7.53  LINUX x86
Copyright (C) SOFNEC CO., LTD. 1987-2013
Compile File = like.pl
[[[ Module = like/FastCode ]]]
A_compiler
WARNING !! NO Public Predicate -> Treat az publicall
 A: Deterministic : like/2
B_compiler
 B: like/2
C_compiler
done!
 C: like/2
gcc -c  -w -O4  userfile.c
gcc -c  -w -O4  like.c
gcc  -o prolog userfile.o like.o    -lazp -lm -ldl

何度も言うけど、出来たアプリを配布するのはルール違反です。

gofer

ここまでは、いわゆるprologの処理系だったけど、簡易な処理系も有ったはず。えっと、どこかで 出あっていたはずだなあと一晩考えたら、hugs98のデモに有ったなと思い出したぞ。

早速ソースを展開してdemos/Prologの中で指示通りに起動してみたんだけど、ファイルが足りないと 文句を言われた。もうメンテナンスしてないんですかね? ならば、hugsの元になったgofer ではどうかと、しつこく探してみたよ。そしたら有った。

Parse       -- general purpose parsing library
Interact    -- general purpose library for interactive programs
PrologData  -- definition of main data structures
Subst       -- substitutions and unification
StackEngine -- inference engine
Main        -- top level program

こんな構成。例にはStackEngineが出てるけど、この他にPureEngineてのとAndorraEngineってのも 提供されてた。エンジンを載せ変えて実験出切るよとな。

そして、AndorraEngineのレファレンスの中に

   Seif Haridi & Per Brand, "Andorra Prolog, an integration of Prolog
   and committed choice languages" in Proceedings of FGCS 1988, ICOT,
   Tokyo, 1988.

こんな一文が。国を挙げて第五世代コンピュータ言語を開発してたんですなあ。そう言えば シグマとか言うOSもやってたような。。その成果は国民に還元されてるんでしょうか?

早速走らせてみる。

[sakae@manjaro Prolog]$ ./gofer + miniProlog.gp
Gofer Version 2.30b  Copyright (c) Mark P Jones 1991-1995
  :
Gofer session for: (project: miniProlog.gp)
standard.prelude
Parse
Interact
PrologData
Subst
StackEngine
Main
Type :? for help
? main
Mini Prolog Version 1.5g (stack based)

Reading stdlib........done
> ??
append(nil,X,X).
append(cons(X,Y),Z,cons(X,W)):-append(Y,Z,W).

equals(X,X).

not(X):-X,!,false.
not(X).

or(X,Y):-X.
or(X,Y):-Y.

true.

どうやら起動したようです。appendが定義されてたので、試してみます。説明によると、 リストの表現が面倒なので、cons表現してるよーー との事です。

>  ?- append(cons(1,nil),cons(2,nil),X)
X = cons(1,cons(2,nil))
> bye
Thank you and goodbye

(17853 reductions, 33462 cells)

出てきたリストが正しいか、sbclで確認。

[sakae@manjaro ~]$ sbcl
This is SBCL 1.1.15, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

* (cons 1 (cons 2 nil))

(1 2)

Oh! 正しいです。(って、少々、しらじらしいぞ)

SICP

更に記憶を巻き戻すと、SICPでも取り上げられていたような。。ええ、prologって高らかには 言ってないんですけど、4章に論理型プログラミングってのが有った。

SICPの1版の方を見たら、米国では、Pascal PL/I Adaと浮かれてた頃、日本では、Lispから prologへと舵を切ったと、米国の連中が脅威を感じてますなあ。

内容はすっかりと忘れて いるんで、読んでみたよ。前の章からの積み重ねになってるんで、危うくバックトラックして 1章まで戻りそうだったけど、そこは、ちゃんとカットオペレータを働かせましたけどね。 例は、簡易型なんで、カットの事等は出てきませんが。

分かった積もりになるのは罪悪なんで、論よりRunの方針で行きます。SICPに載ってるコードは、 codeに公開されてるので、取ってくる。 日本語版の本は絶版になっちゃんで、Webで公開されたんだけど、 こちらに読めるよ。

で、このコードを走らせて、あやふやな所をtraceでもしてみようと、FreeBSDに入ってる chickenで試したんだけど、

[sakae@fb10 ~/src/sicp]$ csi ch4-query.scm
Error: unbound variable: the-empty-stream

        Call history:

        <syntax>          [tree-walk] (pair? e)
        <syntax>          [tree-walk] (##core#begin (or (tree-walk (car e)) (tree-walk (cdr e))))
        <syntax>          [tree-walk] (or (tree-walk (car e)) (tree-walk (cdr e)))
        <syntax>          [tree-walk] (##core#let ((tmp188 (tree-walk (car e)))) (##core#if tmp188 tmp188 (or189 (tree-walk (cdr e)))))
        <syntax>          [tree-walk] (##core#begin (##core#if tmp188 tmp188 (or189 (tree-walk (cdr e)))))
        <syntax>          [tree-walk] (##core#if tmp188 tmp188 (or189 (tree-walk (cdr e))))
        <syntax>          [tree-walk] (or189 (tree-walk (cdr e)))
        <syntax>          [tree-walk] (tree-walk (cdr e))
        <syntax>          [tree-walk] (cdr e)
        <syntax>          [tree-walk] (tree-walk (car e))
        <syntax>          [tree-walk] (car e)
        <syntax>          [tree-walk] (##core#begin false)
        <syntax>          [depends-on?] (tree-walk exp)
        <syntax>          [depends-on?] (##core#undefined)
        <syntax>          (define THE-ASSERTIONS the-empty-stream)
        <syntax>          (##core#set! THE-ASSERTIONS the-empty-stream) <--

変数が束縛されてないって言われるんで、少しコードとにらめっこすれば何とかなりそう。 だけど、先を急ぐので、 Fedoraに入れてるgaucheで試すと、

[sakae@fedora sicp]$ gosh ch4-query.scm
gosh: "error": Compile Error: cannot find "var" in ("/usr/share/gauche-0.9/site/lib" "/usr/share/gauche-0.9/0.9.3.3/lib" "/usr/share/gauche/site/lib" "/usr/share/gauche/0.9/lib")
"./ch4-query.scm":161:(define (extend-if-consistent var da ...

これはもう、 MIT/GNU Schemeを入れろと言う神の啓示に 違いない。素直に、万次郎Linuxに入れてあげたよ。

mit-schemeは利用者の便の為、edwinって 言うemacsもどきが付いているんだけど、CUI環境でscheme --edit なんて起動すると 悲惨な状況になる。これはもう、emacsで動かす鹿ないな。取り寄せたソースツリーの 中の、 etc/xscheme.el を.emacs.d/の中に突っ込んだら、M-x run-schemeでmit-schemeが起動して きたぞ。こりゃ楽でいいわい。

MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.

Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Image saved on Tuesday November 8, 2011 at 10:40:30 PM
  Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/i386 4.118
  Edwin 3.116

1 ]=> (load "ch4-query.scm")

;Loading "ch4-query.scm"... done
;Value: microshaft-data-base

1 ]=> (initialize-data-base microshaft-data-base)

;Value: done

1 ]=> (query-driver-loop)


;;; Query input:
(job ?x (computer programmer))

;;; Query results:
(job (fect cy d) (computer programmer))
(job (hacker alyssa p) (computer programmer))

;;; Query input:
(address ?x ?y)

;;; Query results:
(address (aull dewitt) (slumerville (onion square) 5))
(address (cratchet robert) (allston (n harvard street) 16))
(address (scrooge eben) (weston (shady lane) 10))
(address (warbucks oliver) (swellesley (top heap road)))
(address (reasoner louis) (slumerville (pine tree road) 80))
(address (tweakit lem e) (boston (bay state road) 22))
(address (fect cy d) (cambridge (ames street) 3))
(address (hacker alyssa p) (cambridge (mass ave) 78))
(address (bitdiddle ben) (slumerville (ridge road) 10))

;;; Query input:
(and (job ?person (computer programmer))
     (address ?person ?where))

;;; Query results:
(and (job (fect cy d) (computer programmer)) (address (fect cy d) (cambridge (ames street) 3)))
(and (job (hacker alyssa p) (computer programmer)) (address (hacker alyssa p) (cambridge (mass ave) 78)))

後は、このプログラムを司っているストリームの実現方法を見るのと、前の章に出ていた 制約とその伝播の所見ればいいのかな。なんだ、結局バックトラックする訳ね。そして、 SchemeとPrologの幸せな結婚 とかがあるので、覗きにも行ってみるか。

rubyとかでもprolog

gofer(haskellの祖先)やschemeでprologってのを見てきたけど、LLではどうよって言われそう。 そこで、それらを挙げておく。

Rubyで作るProlog処理系

Python で作る Prolog 処理系

Java で作る Prolog 処理系

数学の想像力を読んでいたら、3段論法が出てきた。

プラトン  は 人間 で ある
ソクラテス は 人間 で ある
        人間 は 死ぬ

から、ソクラテスは死ぬってのを論破したり、死ぬのは奴らだから、奴らにソクラテスが 含まれていたりね。

human(plato).
human(socrates).
die(X) :- human(X).

これとサザエさん一家の家系図からの演繹は、まともなprolog説明には必ず出てくるね。 それじゃ、こういうのはどうよ? 風が吹けば桶屋が儲かる。

風が吹くと、土ぼこりがたつ
土ぼこりがたつと、人の目に入る
人の目に入ると、目が見えなくなる
目が見えなくなると、三味線がよく売れる
三味線がよく売れると、猫が減る
猫が減ると、ねずみが増える
ねずみが増えると、桶がかじられる
桶がかじらると、桶がよく売れる
桶がよく売れると、桶屋が儲かる

堂々たる10段論法。若い人には意味が通じない所が有るかも知れないので、補足しとく。 目が見えなくなると、三味線のくだりは、めくらになると三味線を弾いて、生計を立てる ぐらいしか生きる方法は無かった(注 座頭市を除くって、我ながら古いねぇ)。 三味線の胴には猫皮が張ってあった。桶は木と竹で出来ていた。これを考えた人は江戸時代の人?

これをprologのコードに落としなさい。風が吹くと、火事が増える とかやって、10段論法で とんでも無い結論を演繹しなさい。これ、今年の新人の研修テーマになったりしてたら、面白いな。