ラベル Learn Prolog Now の投稿を表示しています。 すべての投稿を表示
ラベル Learn Prolog Now の投稿を表示しています。 すべての投稿を表示

2009年7月9日木曜日

12 Working With Files


* 12 Working With Files
** 1 Splitting Programs over Files
- consult
- [FileName]. (at top-level)
- 実体はconsultという述語らしい。
- ファイルの中で使うときは頭に:-をつけるようだ。
- ensure_loaded
- ensure_loaded([FileName]).は、読み込み済みで無
変更なものは再読み込みしないようだ。
- module
- そのファイルをmoduleにする。
- :- module(ModuleName,
List_of_Predicates_to_be_Exported).
- use_module
- moduleを使う。
- :- use_module(ModuleName).
- importする述語の指定(制限)もできる。
- :- use_module(ModuleName,
List_of_Predicates_to_be_imported).
- library
- 処理系にてライブラリとして定義されているもの
を指定する。use_moduleとあわせて使う。
- 例:
:- use_module(library(lists)).

** 2 Writing to Files
- streamがある。使い方はこんな感じ。

open('hoge.txt',wrie,Stream),
write(Stream,'This is hoge.',nl(Stream),
close(Stream).

** 3 Reading from Files
- read/2
- streamからPrologのtermsを読み込む。
- streamが読むものがないとエラーになる。
- at_end_of_stream/1
- streamの終端の検知。
- get_code/2
- streamからcharacterをひとつ読む。

** 4 Exercise
- Exercise 12.1.

main :-
open('hogwarts.houses',write,Stream),
tab(Stream,10),write(Stream,'glyffindor'),nl(Stream),
tab(Stream,3),write(Stream,'hufflepuff'),tab(Stream,4),write(Stream,'ravenclaw'),nl(Stream),
tab(Stream,10),write(Stream,'slytherin'),nl(Stream),
close(Stream).

- Exercise 12.2.

:- dynamic word/2.

main :-
open('swipl-man.txt',read,S),
doWords(S),
close(S).

readWord(InStream,W) :-
get_code(InStream,Char),
checkCharAndReadRest(Char,Chars,InStream),
atom_codes(W,Chars).

checkCharAndReadRest(10,[],_) :- !.
checkCharAndReadRest(32,[],_) :- !.
checkCharAndReadRest(-1,[],_) :- !.
checkCharAndReadRest(end_of_file,[],_) :- !.
checkCharAndReadRest(Char,[Char|Chars],InStream) :-
get_code(InStream,NextChar),
checkCharAndReadRest(NextChar,Chars,InStream).

doWords(InStream) :-
\+ at_end_of_stream(InStream),
readWord(InStream,W),
writeWord(W),
doWords(InStream).

writeWord(Word) :-
Word \== '', memoize(Word).
writeWord('').

memoize(W) :-
word(W,N),M is N+1,asserta(word(W,M)),retract(word(W,N)),!.
memoize(W) :- asserta(word(W,1)).

** 5 Practical Session
- 今まで作ってきたものをモジュール化して統合。
- モジュール名と、ファイル名の拡張子より前は、同
じでないといけないみたい。
- Step 2までにしておき、後は入出力の練習なので、
割愛する。


読了!!!!
頭がくたくただ!

【LPN】10 Cuts and Negation [落葉拾い]

いずれも寝た後なら簡単だった。疲れたときにも頑張ることは、意味がないのかなぁ。

- Exercise 10.4.

うーん。むずかしい。cutは宣言的かつ手続き的なの
で、慣れれば強力かもしれないが、慣れないと中途
半端で考えにくい。特にunificationがどう効いてく
るかが問題になると、自分で束縛管理した方が楽じゃ
んと思えてしまう。

ここは後日、再チャレンジ。

一晩寝たら5分でできた。。。

directTrain(saarbruecken,dudweiler).
directTrain(dudweiler,saarbruecken).
directTrain(forbach,saarbruecken).
directTrain(saarbruecken,forbach).
directTrain(freyming,forbach).
directTrain(forbach,freyming).
directTrain(stAvold,freyming).
directTrain(freyming,stAvold).
directTrain(fahlquemont,stAvold).
directTrain(stAvold,fahlquemont).
directTrain(metz,fahlquemont).
directTrain(fahlquemont,metz).
directTrain(nancy,metz).
directTrain(metz,nancy).


route(From,To,Route) :- rt(From,To,[To],Route).
rt(From,From,A,A) :- !.
rt(From,To,A,Route) :-
directTrain(From,To),
rt(From,From,[From|A],Route).
rt(From,To,A,Route) :-
directTrain(ViaSt,To),
rt(From,ViaSt,[ViaSt|A],Route).


** 5 Practical Session
- 1.

\+ version.

nu(A,B) :- \+ A = B.

\+ cut-free version

nu(A,B) :-
A = B, fail;
A \= B.

cut-fail combination version

nu(A,B) :- A = B, !, fail.
nu(_,_).

- 2.

頭がまわらないので、これも後日。

これも一晩寝たら30分くらいでできた。

unifiableUni(Term1,Term2) :-
atomic(Term1),atomic(Term2),
Term1 = Term2.
unifiableUni(Term1,Term2) :-
var(Term1);
var(Term2).
unifiableUni(Term1,Term2) :-
complexterm(Term1),
complexterm(Term2),
Term1 =.. [F1|Args1],
Term2 =.. [F2|Args2],
F1 = F2,
unifiableLists(Args1,Args2).
unifiableLists([],[]).
unifiableLists([H1|T1],[H2|T2]) :-
unifiableUni(H1,H2),
unifiableLists(T1,T2).

unifiableAcc([],Term,A,A).
unifiableAcc([H|T],Term,A,R) :-
unifiableUni(H,Term),
unifiableAcc(T,Term,[H|A],R),!;
unifiableAcc(T,Term,A,R).

unifiable(List1,Term,List2) :-
unifiableAcc(List1,Term,[],List2).


こつこつ。

【LPN】11 Database Manipulation and Collecting Solutions


* 11 Database Manipulation and Collecting Solutions
** 1 Database Manipulation
- assert/1。む、swi-prologはちょっと変なことを言う。

?- listing.
true.

?- assert(happy(mia)).
true.

?- listing.

:- dynamic happy/1.

happy(mia).
true.

?-

- ファイルから読み込んだものはstatic predicates、
REPL?で定義したものはdynamic predicates。
- retract : 撤回する
- swi-prologではretractの対象がDBに複数あるとき、
バックトラック的な操作で全て消せる。

?- retract(happy(vincent)).
true ;
true.

?- listing.

:- dynamic happy/1.

happy(butch).

:- dynamic naive/1.

naive(A) :-
happy(A).
true.

?-

- assertはmemoisaitonに使える。
- database manipulationの迂闊な利用はnightmareだか
ら注意して。

** 2 Collecting Solutions
- findall/3はちょっとmap的。
- bagof/3、便利。
- setof/3、便利。

** 3 Exercise
- Exercise 11.1.
- 第一段階

q(foo,blug).
q(a,b).
q(1,2).

- 第二段階

q(foo,blug).
q(a,b).
p(X) :- h(X).

- 第三段階

p(X) :- h(X).

- Exercise 11.2.
- findall(X,q(blob,X),List).
List = [blug,blag,blig].
- findall(X,q(X,blug),List).
List = [blob,dang].
- findall(X,q(X,Y),List).
List = [blob,blob,blob,,blaf,dang,dang,flab].
- bagof(X,q(X,Y),List).
Y = blug,
List = [blob,dang].
Y = blag,
List = [blob,blaf].
Y = blig,
List = [blob].
Y = dong,
List = [dang].
Y = blob,
List = [flab].
- setof(X,Y^q(X,Y),List).
List = [blaf,blob,dang,flab].

- Exercise 11.3.
- まずこう書いた。
sigma(0,0).
sigma(N,S) :-
M is N - 1, M >= 0,
T is S - N, T >= 0,
sigma(M,T),!,
asserta((:- sigma(N,S))).

- これはpredicateとしては使えるが、構築には使え
ない。

?- sigma(5,15).
true.

?- sigma(10,X).
ERROR: is/2: Arguments are not sufficiently instantiated
^ Exception: (9) _L143 is _G174-10 ?

- traceで調べる。

?- trace.
Unknown message: query(yes)
[trace] ?- sigma(2,X).
Call: (7) sigma(2, _G303) ?
^ Call: (8) _L180 is 2-1 ?
^ Exit: (8) 1 is 2-1 ?
^ Call: (8) 1>=0 ?
^ Exit: (8) 1>=0 ?
^ Call: (8) _L181 is _G303-2 ?
ERROR: is/2: Arguments are not sufficiently instantiated
^ Exception: (8) _L181 is _G303-2 ?
Exception: (7) sigma(2, _G303) ?
?-

- なるほど。Unificationのinstantiationがいまい
ちつかめていないのだな。accumulatorを使おう。

sigma(N,S) :- sigmaAcc(N,0,S),!,asserta((sigma(N,S))).
sigmaAcc(0,A,A) :- !.
sigmaAcc(N,A,S) :-
M is N - 1,
NewA is A + N,
sigmaAcc(M,NewA,S).

assertaが

ERROR: asserta/1: No permission to modify static_procedure `sigma/2'

を吐く。これはまた別の問題なので割愛する。

** 4 Practical Session
- 1.

subset([],_).
subset([H|T],[H|ST]) :-
subset(T,ST).
subset([H|T],[SH|[H|ST]]) :-
subset(T,[SH|ST]).

backtrackで出力する集合に重複があるけどそれは勘
弁。

- 2.

powerset(L,P) :-
findall(X,subset(X,L),P).

先の重複の問題があるので、同じ集合だけど並びが
違うものも含んでしまっている。

?- powerset([a,b,c],P).
P = [[], [a], [a, b], [a, b, c], [a, c], [a, c, b], [b], [b|...], [...|...]|...].

これらの手落ちは後日時間があったらやろう。


よろよろ。

2009年7月8日水曜日

【LPN】10 Cuts and Negation


* 10 Cuts and Negation
** 1 The Cut
- ! : predicate called cut.
- cutは常に成功する。副作用する。副作用が大事。
- fat-freeじゃなくてcut-free。
- commit A to do,doing : Aに...することを義務づけ
る。
- cutを踏んだ時点で2つのことが義務となる。1つめは、
現在のproof searchにおいて、そのclauseのみを探
索の対象とすること(他のclauseは除外するというこ
と)。次に、cutを踏む前にunify済みの変数について
は、これ以降unificationは実施しないこと。
** 2 Using Cut
- green cuts : cutsを入れても入れなくてもプログラ
ムの意味(入出力の対応)に変化はないもの。green
cutsに意味があるのは、効率があがるときである。
- red cuts : cutsの有り無しでプログラムの意味が変
わるcuts。
- red cutsがある、ということはそのプログラムがあ
まり宣言的ではない証左。なるほど。
** 3 Negation as Failure
- fail/0 : バックトラックを強制する述語。
- cut-fail combination : failによるバックトラック
を抑制するイディオム。このイディオムがくると、
そこでproof search自体がfailする(バックトラック
しない)。
- この章に入って、Prologの手続き的側面がどんどん
導入されていく。。
- negation : Monadic Boolean operations whose
result have the Boolean value opposite to that
of the operand.
- cut-failじゃなくてnegation as failureを使うほう
が安全。

neg(Goal) :- Goal,!,fail.
neg(Goal).

- \+ : built-in negation as failure predicate.

- cutsとnegation as failureの使い方についての完全
なルールは存在しないケースバイケースの判断が必
要。

- まあ、プログラミングは、科学であるのと同じくら
い芸術(技芸)でもあるので、自身が選択した言語と
問題領域について理解を常に深めなければならない。
だから面白いんだよ、プログラミングは。など。
** 4 Exercises
- Exercise 10.1.
p(X).
X = 1.
X = 2.

p(X),p(Y).
X = 1, Y = 1.
X = 1, Y = 2.

これ、間違えた。正解は、


?- p(X),p(Y).
X = 1,
Y = 1 ;
X = 1,
Y = 2 ;
X = 2,
Y = 1 ;
X = 2,
Y = 2.

?-

ということ。p(Y)でのcutはp(X)の探索には影響を及
ぼさないことに注意。

p(X),!,p(Y).
X = 1, Y = 1.
X = 1, Y = 2.

- Exercise 10.2.

class(Number,positive) :- Number > 0.
class(0,zero).
class(Number,negative) :- Number < 0.

これは数字のクラスに関する述語。正か負かゼロか
でクラス分けしている。

green cutsによる効率化。

class(Number,positive) :- Number > 0,!.
class(0,zero) :- !.
class(Number,negative) :- Number < 0.

- Exercise 10.3.

まず、cut-free。

split([],[],[]).
split([LH|LT],[LH|PT],N) :-
LH >= 0, split(LT,PT,N).
split([LH|LT],P,[LH|NT]) :-
LH < 0, split(LT,P,NT).

続いてgreen cuts。

split([],[],[]) :- !.
split([LH|LT],[LH|PT],N) :-
LH >= 0, !, split(LT,PT,N).
split([LH|LT],P,[LH|NT]) :-
LH < 0, !, split(LT,P,NT).

- Exercise 10.4.

うーん。むずかしい。cutは宣言的かつ手続き的なの
で、慣れれば強力かもしれないが、慣れないと中途
半端で考えにくい。特にunificationがどう効いてく
るかが問題になると、自分で束縛管理した方が楽じゃ
んと思えてしまう。

ここは後日、再チャレンジ。



** 5 Practical Session
- 1.

\+ version.

nu(A,B) :- \+ A = B.

\+ cut-free version

nu(A,B) :-
A = B, fail;
A \= B.

cut-fail combination version

nu(A,B) :- A = B, !, fail.
nu(_,_).

- 2.

頭がまわらないので、これも後日。


よろよろ。

【LPN】9 A Closer Look at Terms


* 9 A Closer Look at Terms
** 1 Comparing Terms
- ==/2はCommon Lispのeqみたいなニュアンスかな。

?- a == a.
true.

?- a == b.
fail.

?- a == 'a'.
true.

?- X == Y.
fail.

?- X=Y.
X = Y.

?- a = X, a == X.
X = a.

?-

- ふむ、eval、、、ではなくunifyされたobjectsを
eq、、、じゃなく==は等価性チェックする。
- ただ、==はtrue/failだけでなく、unifyされている
ときは、unification(binding)を返しているな。な
んか気になる。
- \==/2の導入。

** 2 Terms with a Special Notation
- Arithmetic terms

?- (2 =:= 3) == =:=(2,3).
true.

?- 2 =:= 3 == =:=(2,3).
ERROR: Syntax error: Operator priority clash
ERROR: 2 =:=
ERROR: ** here **
ERROR: 3 == =:=(2,3) .
?-

- なるほど。

- List as terms

?- .(a,[]) == [a].
true.

?- .(a,.(b,[])) == [a,b].
true.

?-
- おお、consだ!会いたかったよ、cons。こんなに小
さくなっちゃって。。。

** 3 Examining Terms
- Types of Terms
- termsの型を調べる述語たち。

- The structure of Terms

?- functor(f(a,b),F,A).
F = f,
A = 2.

?-
- おお、functorとarityも取れるのね。

?- functor(T,hoge,1).
T = hoge(_G240).

- 構成もしてくれる、と。

- complex termに対する型判定述語は自分で作る。

complexterm(X) :-
nonvar(X),
functor(X,_,A),
A > 0.

- arg : 引数に対するアクセス。
- =.. : complex termsのfunctorとargsをリストで返
す。univと呼ばれる。
- atom_codes/2にてatomとstringの相互変換ができる。

** 4 Operators
- ?-というのはprefix operatorだったのか。
- precedenceが大きいものが主たる(:外側の)functor
になる。+と*でいうと+の方が優先度が大きいので

2 + 3 * 4.

は、

+(2,*(3,4)).

になる。優先度が高い = 結合度が低い、かな。

- operatorsとpredicatesが同義語なのかそうでないの
かがわからない。先々わかるかな。
- precedenceが同じoperatorsが存在する場合どうなる
か。それはoperatorsのassociativityという概念/機
構によって振る舞いがきまる。
- 例えば、+は左結合性をもっている(left
associative)。
- 左結合性をは何か?
- まずexpressionsのprecedenceの概念がある。それは
そのexpressionの主functorのprecedenceである。さ
て、左結合性とは、infix operatorsなのでそもそも
引数は左右の2つなのだが、左にいれるexpressionは
自身と同じprecedenceでもよいが、右にいれる
expressionは自身より低くないといけない。これに
よって、

2 + 3 + 4.

は、

+(+(2,3),4).

というように曖昧さなく解釈される。ためす。

?- 2 + 3 + 4 = +(+(2,3),4).
true.

?- 2 + 3 + 4 = +(2,+(3,4)).
fail.

なお、これは内側のoperatorが+でなくても(同じで
なくても)適用される。

- ==, =:= は同じprecedenceを持ち、かつ
non-associtiveである。すなわち、左右引数双方と
も自身よりもprecedenceが低い必要がある。そのた
め、

2 =:= 3 == =:=(2,3).

が、

==((2 =:= 3),=:=(2,3)).

なのか、

=:=(2,==(3,=:=(2,3))).

なのかをPrologは自動判定できない。

- Defining operators
- operatorsというのは、operatorとして構文定義され
たpredicatesのことのようだな。逆に言うと、op
operatorが定義するのは構文だけで、それの意味と
いうかその演算の結果がどうなるかは通常のqueryと
同じであるということ。

?- assert(kill(marcellus,zed)).
true.

?- kill(X,zed).
X = marcellus.

?- assert((is_dead(X) :- kill(_,X))).
true.

?- is_dead(zed).
true.

?- op(500,xf,is_dead).
true.

?- zed is_dead.
true.

?- is_dead zed.
ERROR: Syntax error: Operator expected
ERROR: is_dead
ERROR: ** here **
ERROR: zed .

?-

** 5 Exercise
- Exercise 9.1.
- 12 is 2*6.
true.
- 14 =\= 2*6.
true.
- 14 = 2*7.
true. /* 正しくはfail。unifyは計算しない。term
の種類が違う。*/
- 14 == 2*7.
fail.
- 14 \== 2*7.
true.
- 14 =:= 2*7.
true.
- [1,2,3|[d,e]] == [1,2,3,d,e].
true.
- 2+3 == 3+2.
fail.
- 2+3 =:= 3+2.
true.
- 7-2 =\= 9-2.
true.
- p == 'p'.
true.
- p =\= 'p'.
fail. /* 正しくはERROR.数字じゃないので計算で
きない */
- vicent == VAR.
fail
- vincent=VAR,VAR==vincent.
true.

- Exercise 9.2.
- .(a,.(b,.(c,[]))) = [a,b,c].
true.
- .(a,.(b,.(c,[]))) = [a,b|c].
fail
- .(.(a,[]),.(b,[]),.(.(c,[]),[])) = X.
ERROR. /* 最外の.の引数が3つ。*/
お、ERRORにならない。そうか'.'/3が定義されるの
か!
- .(a,.(b,.(.(c,[]),[]))) = [a,b|[c]].
fail. /* [a,b,[c]] */
- Exercise 9.3.

complexterm(X) :-
nonvar(X),
functor(X,_,A),
A > 0.

termtype(Term,atom) :-
atom(Term).
termtype(Term,number) :-
number(Term).
termtype(Term,constant) :-
atomic(Term).
termtype(Term,variable) :-
var(Term).
termtype(Term,simple_term) :-
atomic(Term);
var(Term).
termtype(Term,comprex_term) :-
complexterm(Term).
termtype(_,term).

- Exercise 9.4.

groundterm(X) :-
atomic(X), nonvar(X).
groundterm(X) :-
nonvar(X),
X = [H|T],
groundterm(H),
groundterm(T).
groundterm(X) :-
complexterm(X),
'=..'(X,[functor|Args]),
groundterm(Args).

- Exercise 9.5.

- うー。operatorの結合めんどくさい。S式でいいじゃん。

X is_a witch
is_a(X,witch).

harry and ron and hermione are friends
are(and(harry,and(ron,haermione)),friends)

harry is_a wizard and likes quidditch
illegal.

dubledore is_a famous wizard
is_a(dubledore,famous(wizard)).

** 6 Practical Session
- pretty printer

pptree(T) :- ppt(T,0).
ppt(T,I) :-
atomic(T),tab(I),write(T).
ppt(T,I) :-
complexterm(T),
'=..'(T,[Functor,Single]),
tab(I),write(Functor),write('('),write(Single),write(')').
ppt(T,I) :-
complexterm(T),
'=..'(T,[Functor,Left,Right]),
tab(I),write(Functor),write('('),nl,
NewI is I + 2,
ppt(Left,NewI),nl,
ppt(Right,NewI),write(')').

- propositional logic formulas

:- op(200,fx,not).
:- op(300,xfy,implies).


さすがに体調が悪くなってきた。
仕事との両立が難しいのか、体が弱いのか。

こつこつ。

2009年7月7日火曜日

【LPN】8 More Definete Clause Grammars


* 8 More Definete Clause Grammars
- defineteということはindefineteもあるのかどうか、
というのが気になる。
** 1 Extra Arguments
- Context free grammars with features
- 代名詞の導入。
s --> np_subject,vp.

np_subject --> det,n.
np_object --> det,n.
np_subject --> pro_subject.
np_object --> pro_object.

vp --> v,np_object.
vp --> v.

det --> [the].
det --> [a].

n --> [woman].
n --> [man].

v --> [shoots].

pro_subject --> [he].
pro_subject --> [she].
pro_object --> [him].
pro_object --> [her].

- lexicon : 辞書
- 代名詞をいれただけで、これだけ文法を書きかえな
ければいけないのはうまくない。また、代名詞と名
詞は多くの性質を共有しているのにそれをまったく
別に定義する、というのもうまくない。
- これらをうまくやるのがextra arguments。

s --> np(subject),vp.

np(_) --> det,n.
np(X) --> pro(X).

vp --> v,np(object).
vp --> v.

det --> [the].
det --> [a].

n --> [woman].
n --> [man].

v --> [shoots].

pro(subject) --> [he].
pro(subject) --> [she].
pro(object) --> [him].
pro(object) --> [her].

- npにfeaturesを追加した。
- DCG with argumentsは、言語処理のための最新のツー
ルではない。しかし単なるおもちゃでもない。相当に
洗練された文法を記述できる。

- Building parse tree
- うーん、

s(np(det(a),n(woman)),vp(v(shoots))).

(s (np (det a) (n woman)) (vp (v shoots)))

S式の方が見易いと思うんだけどなぁ。まあそれは
PAIPで。

- extra argumentsを利用してparserにする。

s(s(NP,VP)) --> np(NP),vp(VP).

np(np(DET,N)) --> det(DET),n(N).

vp(vp(V,NP)) --> v(V),np(NP).
vp(vp(V)) --> v(V).

det(det(the)) --> [the].
det(det(a)) --> [a].

n(n(woman)) --> [woman].
n(n(man)) --> [man].

v(v(shoots)) --> [shoots].

- DRYではないが、書けるぞ、という感じ。
- extra argsは、semantic representationsを構築す
るのにも便利につかえる。
- semantic representationsはformal languagesによっ
て記述される。例えば、
- first order logic
- discourse representation structures
: 談話言語表示理論
- a database query language
- これらはcompositonaryに構築される。
- というのは単純にそれぞれの単語の意味を結合する
だけではなくて、parse treeの構造をみつつ、意味
を構築していく。

- Beyond context free language
- DCGはCFG以外の文法も記述できる。
- 例えば、{a^nb^nc^n\{e}}。

s(Count) --> ablock(Count),bblock(Count),cblock(Count).
ablock(0) --> [].
ablock(succ(Count)) --> [a],ablock(Count).
bblock(0) --> [].
bblock(succ(Count)) --> [b],bblock(Count).
cblock(0) --> [].
cblock(succ(Count)) --> [c],cblock(Count).

** 2 Extra Goals
- DCGの右側ではPrologの機能を使える。
- それはextra goalsとして、であり、{}で囲む。

s --> ablock(Count),bblock(Count),cblock(Count).
ablock(0) --> [].
ablock(NewCount) --> [a],ablock(Count),
{NewCount is Count + 1}.
bblock(0) --> [].
bblock(NewCount) --> [b],bblock(Count),
{NewCount is Count + 1}.
cblock(0) --> [].
cblock(NewCount) --> [c],cblock(Count),
{NewCount is Count + 1}.
- なお、これはrecogniserとしてのみ使える。

- Separating rules and lexicon
- Extra Goalsの有用な応用として文法と辞書の分離が
ある。
- 自然言語のlexiconsは巨大になるので実戦においても
メリットがある。
- Prologはfirst argment indexingを実施しているの
で、効率もよくなる。
** 3 Concluding Remarks
- DCGはturing-complete。
- "all top-down parsers loop on left-recursive
grammars." なるほど。
- なお、DCGという記法に何か問題があるわけではない。
それのPrologの解釈(実行する手続き)に注意が必要
だということだ。syntaxとsemanticsの分離というこ
とか。
** 4 Exercise
- Exercise 8.1.

s --> np(X),vp(X).

np(X) --> det(X),n(X).
vp(X) --> v(X),np(_).
vp(X) --> v(X).

det(plur) --> [the].
det(sing) --> [the].
det(sing) --> [a].

n(sing) --> [woman].
n(sing) --> [man].
n(sing) --> [apple].
n(sing) --> [pear].
v(plur) --> [eat].

n(plur) --> [women].
n(plur) --> [men].
n(plur) --> [apples].
n(plur) --> [pears].
v(sing) --> [eats].

- Exercise 8.2.

kanga(V,R,Q,A,C) :-
roo(V,R,A,B),
jumps(Q,Q,B,C),
marsupiral(V,R,Q).

** 5 Practical Session

- 1.

lex(woman,n,sing).
lex(man,n,sing).
lex(apple,n,sing).
lex(pear,n,sing).
lex(women,n,plur).
lex(men,n,plur).
lex(apples,n,plur).
lex(pears,n,plur).

lex(a,det,sing).
lex(the,det,sing).
lex(the,det,plur).

lex(eat,v,plur).
lex(eats,v,sing).

lex(he,pro,sing,subj).
lex(she,pro,sing,subj).
lex(him,pro,sing,obj).
lex(her,pro,sing,obj).


s(s(NP,VP)) --> np(NP,X,subj),vp(VP,X).

np(np(DET,N),X,_) --> det(DET,X),n(N,X).
np(np(PRO),X,Y) --> pro(PRO,X,Y).
vp(vp(V,NP),X) --> v(V,X),np(NP,X,obj).
vp(vp(V),X) --> v(V,X).

det(det(Word),X) --> [Word],{lex(Word,det,X)}.
n(n(Word),X) --> [Word],{lex(Word,n,X)}.
v(v(Word),X) --> [Word],{lex(Word,v,X)}.
pro(pro(Word),X,Y) --> [Word],{lex(Word,pro,X,Y)}.

- 2.
/* lexicon */
lex(woman,n,sing,third).
lex(women,n,plur,third).
lex(man,n,sing,third).
lex(men,n,plur,third).
lex(apple,n,sing,third).
lex(apples,n,plur,third).
lex(pear,n,sing,third).
lex(pears,n,plur,third).

lex(a,det,sing).
lex(the,det,sing).
lex(the,det,plur).

lex(eat,v,plur,third).
lex(eats,v,sing,third).
lex(eat,v,plur,first).
lex(eat,v,sing,first).
lex(eat,v,plur,second).
lex(eat,v,sing,second).

lex(i,pro,sing,subj,first).
lex(me,pro,sing,obj,first).
lex(you,pro,sing,subj,second).
lex(you,pro,sing,obj,second).
lex(he,pro,sing,subj,third).
lex(him,pro,sing,obj,third).
lex(she,pro,sing,subj,third).
lex(her,pro,sing,obj,third).

lex(in,prep).
lex(on,prep).
lex(under,prep).
lex(over,prep).

lex(small,adj).
lex(big,adj).
lex(beautiful,adj).
lex(frightened,adj).
lex(fat,adj).
lex(tall,adj).

s(s(GNP,VP)) --> gnp(GNP,SP,subj,Person),vp(VP,SP,Person).

/* general noun phrases */
gnp(gnp(PRO),SP,SO,Person) --> pro(PRO,SP,SO,Person).
gnp(gnp(NP),SP,_,Person) --> np(NP,SP,_,Person).

/* noun phrases */
np(np(DET,NC),SP,_,Person) --> det(DET,SP),nc(NC,SP,Person).
np(np(NP,PP),SP,SO,Person) --> np(NP,SP,SO,Person),pp(PP).

/* noun cores */
nc(nc(N),SP,Person) --> n(N,SP,Person).
nc(nc(ADJ,NC),SP,Person) --> adj(ADJ), nc(NC,SP,Person).

/* preposition phrase */
pp(pp(PREP,GNP)) --> prep(PREP), gnp(GNP,_,obj,_).

/* verb phrases */
vp(vp(V),SP,Person) --> v(V,SP,Person).
vp(vp(V,GNP),SP,Person) --> v(V,SP,Person),gnp(GNP,SP,obj,_).

/* load lexicon */
det(det(Word),SP) --> [Word],{lex(Word,det,SP)}.
n(n(Word),SP,Person) --> [Word],{lex(Word,n,SP,Person)}.
v(v(Word),SP,Person) --> [Word],{lex(Word,v,SP,Person)}.
pro(pro(Word),SP,SO,Person) --> [Word],{lex(Word,pro,SP,SO,Person)}.
prep(prep(Word)) --> [Word],{lex(Word,prep)}.
adj(adj(Word)) --> [Word],{lex(Word,adj)}.


えっと、、、、
形容詞を問題文のように入れると無限ループが発
生するので、いろいろ支障があると思うのだが。形容
詞は2個までとか制限をつけるのかなぁ


最後の課題が結構タフだった。
こつこつ。

【LPN】7 Definite Clause Grammars


* 7 Definite Clause Grammars
** 1 Context Free Grammars
- Prologは多様な目的に利用できるが、発明時の目的と
してcomputational linguistics (計算言語学?、計
算機言語学?)があった。
- Prologにはcomputational linguisticsに有効なツー
ルがたくさんある。
- その筆頭がDCGである。
- DCGは文法を記述するための記法である。
- そもそも文法って何だ。CFGをもってそれを考える。
- CFGの説明。
- CFGはシプサでやったので、用語だけ確認しておく。
- non-terminal symbols
- terminal symbols
- context free rules
- -> : can consist of, can be built out of.
- parse tree : parseは品詞を記述する、構成要素に
分析するという意味らしい。websterだと、Analyze
syntactically by assingning a constituent
structure to (a sentence).
- licensed : "every part of the tree is licesed
by one of our rules", 認可された
- strings : ここではstring of wordsというように
wordの並びをstringという。
- structure : parse treeのもつ構造のこと。
- grammatical : the stringが(given grammarにおい
て)grammaticalであるとは、その文法規則によって
parse treeを構成できることを言う。
- language generated by a grammar : その文法要素
によって生成可能な全てのstringsの総体をこのよ
うに呼ぶ。
- recogniser : stringsがgiven grammarにて生成可
能かどうか判定するプログラム。
- parser : recogniserの機能に加えて、the
structureを示すもの。具体的にはparse treeを示
すもの。
- context free language : context free grammarで
文法を記述可能な言語達のこと。英語はCFGと考え
られている。ドイツ語はCFGでは無いことが証明さ
れている。

- まず、CFGのrecognizerをPrologでどう作るか。
- stringsはlistsとする。
- 対象CFG。

s -> np vp
np -> det n
vp -> v np
vp -> v
det -> 'a
det -> 'the
n -> 'woman
n -> 'man
v -> 'shoots

(注)italic表示のかわりに'を頭につけている。
terminalたちです。

- appendを使う素朴なやり方。
- その1。

s(Z) :- np(X), vp(Y), append(X,Y,Z).
np(Z) :- det(X), n(Y), append(X,Y,Z).
vp(Z) :- v(X), np(Y), append(X,Y,Z).
vp(Z) :- v(Z).
det([the]).
det([a]).
n([woman]).
n([man]).
v([shoots]).

- 動く。しかし、入力情報を探索のガイドにつかって
いないので非効率的。

- その2。
- goalsの順番を変えてみる。

s(Z) :- append(X,Y,Z), np(X), vp(Y).
np(Z) :- append(X,Y,Z), det(X), n(Y).
vp(Z) :- append(X,Y,Z), v(X), np(Y).
vp(Z) :- v(Z).
det([the]).
det([a]).
n([woman]).
n([man]).
v([shoots]).

- 動く。しかしappendとinstansiationsの組み合わせ
は非効率的。traceをみる。

[trace] ?- np([a,woman]).
Call: (7) np([a, woman]) ?
Call: (8) append(_L179, _L180, [a, woman]) ?
Exit: (8) append([], [a, woman], [a, woman]) ?
Call: (8) det([]) ?
Fail: (8) det([]) ?
Redo: (8) append(_L179, _L180, [a, woman]) ?
Call: (9) append(_G366, _L180, [woman]) ?
Exit: (9) append([], [woman], [woman]) ?
Exit: (8) append([a], [woman], [a, woman]) ?
Call: (8) det([a]) ?
Exit: (8) det([a]) ?
Call: (8) n([woman]) ?
Exit: (8) n([woman]) ?
Exit: (7) np([a, woman]) ?
true

- もっとうまい方法はないか。
- ある。
- difference listsという方法。(差分リストとでも言
うのかなぁ)

- difference listsは、2つのリストの差によって対象
となるリストを表現する。

- difference lists版。

s(X,Z) :- np(X,Y), vp(Y,Z).
np(X,Z) :- det(X,Y), n(Y,Z).
vp(X,Z) :- v(X,Y), np(Y,Z).
vp(X,Z) :- v(X,Z).

det([the|W],W).
det([a|W],W).

n([woman|W],W).
n([man|W],W).

v([shoots|W],W).

- これ、昨日flatten書くときに使った手法だ。
- この手法にdifferencial listsという名前をつけて、
汎用化するところが頭いいな。

[trace] ?- s([a,woman,shoots,a,man],[]).
Call: (7) s([a, woman, shoots, a, man], []) ?
Call: (8) np([a, woman, shoots, a, man], _L180) ?
Call: (9) det([a, woman, shoots, a, man], _L198) ?
Exit: (9) det([a, woman, shoots, a, man], [woman, shoots, a, man]) ?
Call: (9) n([woman, shoots, a, man], _L180) ?
Exit: (9) n([woman, shoots, a, man], [shoots, a, man]) ?
Exit: (8) np([a, woman, shoots, a, man], [shoots, a, man]) ?
Call: (8) vp([shoots, a, man], []) ?
Call: (9) v([shoots, a, man], _L234) ?
Exit: (9) v([shoots, a, man], [a, man]) ?
Call: (9) np([a, man], []) ?
Call: (10) det([a, man], _L252) ?
Exit: (10) det([a, man], [man]) ?
Call: (10) n([man], []) ?
Exit: (10) n([man], []) ?
Exit: (9) np([a, man], []) ?
Exit: (8) vp([shoots, a, man], []) ?
Exit: (7) s([a, woman, shoots, a, man], []) ?
true

- うーん。きれい。
- さて、differece listsを使ったrecogniserはかきぶ
りがちょっと汚い。
- そこでDCGの出番。

** 2 Definite Clause Grammars

- DCGは、difference listsを隠蔽してくれるa nice
notation。
- 例。

s --> np,vp.
np --> det,n.
vp --> v,np.
vp --> v.
det --> [the].
det --> [a].

n --> [woman].
n --> [man].

v --> [shoots].

- うむ。構文糖衣というかDSLというか。
- Prologがこれをdifferece listsを使った先の書きぶ
りに変換するとのこと。試す。

?- listing(s).
s(A, C) :-
np(A, B),
vp(B, C).

true.

?-

- ルール追加。

s --> s,conj,s.
conj --> [and].
conj --> [or].
conj --> [but].

- このs,conj,sのsが左再帰問題。
- 語彙を変える。

s --> simple_s.
s --> simple_s,conj,s.
simple_s --> np,vp.
np --> det,n.
vp --> v,np.
vp --> v.
det --> [the].
det --> [a].

n --> [woman].
n --> [man].

v --> [shoots].

conj --> [and].
conj --> [or].
conj --> [but].

- そっか。CFGでnon-terminalについて名前を工夫し
ているときってこういう理由だったんだな。PAIPも
そうやってた。

- formal languageってnatural languageと対を成す
単語なんだ。
- 形式言語(a^n)(b^n)。シプサの世界だ。

s --> [].
s --> l,s,r.

l --> [a].
r --> [b].

** 3 Exercises
- Exercise 7.1.
s(A,D) :-
foo(A,B),bar(B,C),wiggle(C,D).
foo([choo|W],W).
foo(X,Z) :-
foo(X,Y),foo(Y,Z).
bar(X,Z) :-
mar(X,Y),zar(Y,Z).
mar(X,Z) :-
me(X,Y),my(Y,Z).
me([i|W],W).
my([am|W],W).
zar(X,Z) :-
blar(X,Y),car(Y,Z).
blar([a|W],W).
car([train|W],W).
wiggle([toot|W],W).
wiggle(X,Z) :-
wiggle(X,Y),wiggle(Y,Z).

- Exercise 7.2.
s --> l,r.
s --> l,s,r.

l --> [a].
r --> [b].

- Exercise 7.3.
s --> [].
s --> l,s,r,r.

l --> [a].
r --> [b].

** 4 Practical Session
- 1.
s --> [].
s --> w,s,w.
w --> [a].

- 2.
s --> core.
s --> a,s,d.
core --> [].
core --> b,b,core,c,c.
a --> [a].
b --> [b].
c --> [c].
d --> [d].

- 3.
- propositional logic : 命題論理

prop --> [p].
prop --> [q].
prop --> [r].
prop --> not, prop.
prop --> lparen, prop, or, prop, rparen.
prop --> lparen, prop, and, prop, rparen.
prop --> lparen, prop, imp, prop, rparen.

not --> [not].
or --> [or].
and --> [and].
lparen --> ['('].
rparen --> [')'].
imp --> [implies].


この章おもしろかった。
こつこつ。

2009年7月6日月曜日

【LPN】6 More Lists


* 6 More Lists
** 1 Append
- unificationは構造の構築にも使える。
- そしてunificationで構造の構築を記述すると、構造
の分解にも同じ述語を使える。これがすごい。

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

?- append([a,b],[1,2],X).
X = [a, b, 1, 2].

?- append(X,Y,[a,b,1,2]).
X = [],
Y = [a, b, 1, 2] ;
X = [a],
Y = [b, 1, 2] ;
X = [a, b],
Y = [1, 2] ;
X = [a, b, 1],
Y = [2] ;
X = [a, b, 1, 2],
Y = [] ;
fail.

?-

** 2 Reversing a List
- Exercise 6.1.

doubled(L) :- append(X,X,L).

やっぱ頓知かな。

- Exercise 6.2.

parindrome(L) :- rev(L,X), L = X.

これは簡単。

- Exercise 6.3.

toptail(I,[H,T]) :- append([H|_],[T],I).

あ、仕様を読み間違えている。これはtopとtailから
なるlistをつくる。正しくは、topとtail以外のlist
をつくるのだから、、、、

toptail([_|T],O) :- append(O,[_],T).

頓知。

具体的な入出力例をいろいろ書き下していみるのは、
宣言的プログラミングでも効果的。

- Exercise 6.4.

lastRev(List,X) :- rev(List,[H|_]), H = X.

lastRec([Y],X) :- Y = X.
lastRec([_|T],X) :- lastRec(T,X).

- Exercise 6.5.

swapfl([H1|T1],[H2|T2]) :-
append(X,[H1],T2),
append(X,[H2],T1).

backtrackするとappendがとまらないが。

swapflRec([A,B],[B,A]).
swapflRec([H1,C|T1],[H2,C|T2]) :-
swapflRec([H1|T1],[H2|T2]).

再帰は友達。

- Exercise 6.6.


** Practical Session

- 1.

amember(X,L) :- append(_,[X|_],L).

非効率的だろう。

- 2.

まず、こう書いた。

set(_,[]).
set(L,[H|T]) :- member(H,L), set(L,T).

これは述語としては機能するが、構築には使えない。
構築につかえる書きぶりはより宣言的でなければなら
ない。

set(L,S) :- setBuf(L,[],S).
setBuf([H|T],B,S) :-
member(H,B), setBuf(T,B,S);
setBuf(T,[H|B],S).
setBuf([],B,B).

こちらは、構築にもつかえるが集合の要素の順番が異
なるときの判定には対応していない。まあいいや。


- 3.

うーん。Common Lispならすぐ書ける。

(defun flatten (tree)
(cond ((null tree) nil)
((atom (car tree)) (cons (car tree)
(flatten (cdr tree))))
(t (append (flatten (car tree))
(flatten (cdr tree))))))

PrologのProof Searchで解がでるように宣言を考える
ことにはどういう意味があるんだろう。もしそれに意
味が無いならば、それはPrologのために考えているだ
けであり、無意味になってしまうところがこわい。

Prologが探索型開発に向かないのは、問題の分割がや
りにくいからかな。

自分において、その理由を考えてみるとHtDPのデザイ
ンレシピが適用できないことがある。

論理プログラミングのデザインレシピってつくれない
のだろうか。。。

とりあえず、flatten。

flatten([],[]). /* トリビアルなケース。これ以降ちゃんとしたリストであることが保証される */
flatten([X],F) :- flatten(X,F). /* 余分な全体括弧を除去 */
flatten([[H]|T],F) :- flatten([H|T],F). /* headの余分な括弧を除去 */
flatten([[LHH|LHT]|T],[FH|FT]) :- /* headが(意味のある)リストの場合 */
flatten([LHH|LHT],[FH|XT]),flatten([XT|T],FT).
flatten([FH|LT],[FH|FT]) :- flatten(LT,FT). /* headがリストではない場合 */

こつとしては、はじめはrulesのheadはシンプルにし
てbodyのunificationで分解していく。代入がごとく。
そして動くものができたところで、unificationをま
とめていき不要なvariablesを消す。こうすると多少
探索的に書いていける。

ただし、宣言的プログラミングはその正しさが判別し
やすい、というが、上のflattenはとてもそうは思えな
い。こういうケースもあるのか、私のflattenがいけ
てないのか。


こんなもんでPons Asinorumを渡れたのかなぁ。。。

ふー。やっと折り返し地点。いくら初めての言語とはい
え、まったくの入門書なんだからもっとスピーディにい
かんもんかなぁ。頭がポンコツすぎる。

たかがポンコツ、されどポンコツ。

【LPN】5 Arithmetic


* 5 Arithmetic
** 1 Arithmetic in Prolog
- この本では整数しかやらないよ。
- こんな感じ。
?- 8 is 6+2.
true.

?- 8 is 6 + 2.
true.

?- is(8,+(6,2)).
true.

?- X is 6+2.
X = 8.

?-
- (is 8 (+ 6 2))でもよかったじゃん、と思う。まあ
それはPAIPで、ということで。

** 2 A Closer Look
- +-*/などは単なるfunctorである。
?- X = 3+2.
X = 3+2.

?-
これは単なるUnification。それは=/2が統制してい
る。
- 計算を統さどるのはis。
- isは逆演算はできない点に注意。

?- X is 6+2.
X = 8.

?- 6+2 is X.
ERROR: is/2: Arguments are not sufficiently instantiated

?- X = 2, Y is X*3.
X = 2,
Y = 6.

?- Y = 6, Y is X*3.
ERROR: is/2: Arguments are not sufficiently instantiated
?-

** 3 Arithmetic and Lists
- len/2の実装。
- accumulaterの導入。accLen/3、leng/2。
- 末尾再帰の効用の紹介。

** 4 Comparing Integers
- =:= Common Lispの=みたいなもの。
- =\= Common Lispの\=みたいなもの。
- 比較演算子はinstantiationsを実施しない。
?- X < 3.
ERROR: ?-
- あ、なるほど。制御構造のPrologでの表現はこんな
感じ。

accMax([H|T],A,Max) :-
H > A, accMax(T,H,Max);
H =< A, accMax(T,A,Max).
accMax([],A,A).

** 5 Exercise
- Exercise 5.1.
- 1. X = 3*4.
X = 3*4.
- 2. X is 3*4.
X = 12.
- 3. 4 is X.
ERROR.
- 4. X = Y.
X = Y.
- 5. 3 is 1+2.
true.
- 6. 3 is +(1,2).
true.
- 7. 3 is X+2.
ERROR.
- 8. X is 1+2.
X = 3.
- 9. 1+2 is 1+2.
true.
おお、間違えた。これfail。
isの左引数はis的評価をしないのか。
- 10. is(X,+(1,2)).
X = 3.
- 11. 3+2 = +(3,2).
true.
- 12. *(7,5) = 7*5.
true.
- 13. *(7,+(3,2)) = 7*(3+2).
true.
- 14. *(7,(3+2)) = 7*(3+2).
true.
- 15. 7*3+2 = *(7,+(3,2)).
fail.
- 16. *(7,(3+2)) = 7*(+(3,2)).
true.

- Exercise 5.2.
increment(M,N) :- N is M + 1.
sum(M,N,Sum) :- Sum is M + N.

- Exercise 5.3.
addone([],[]).
addone([H1|T1],[H2|T2]) :-
H2 is H1 + 1, addone(T1,T2).

- 油断するとすぐに手続きから考えてしまう。成立す
べき様子というか条件を考えて素直にそれを記述す
べし。

** 6 Practical Session
- 1
accMin([H|T],A,Min) :-
H < A, accMin(T,H,Min);
H >= A, accMin(T,A,Min).
accMin([],A,A).

- 2

scalarMult(_,[],[]).
scalarMult(N,[LH|LT],[RH|RT]) :-
RH is N * LH, scalarMult(N,LT,RT).

- 3

dot([],[],0).
dot([Ha|Ta],[Hb|Tb],A) :-
Anew is A + Ha * Hb, dot(Ta,Tb,Anew).

だとうまくいかない。accumulatorを使うとうまくいく。

dot_acc([],[],A,A).
dot_acc([Ha|Ta],[Hb|Tb],A,R) :-
Anew is A + Ha * Hb, dot_acc(Ta,Tb,Anew,R).
dot(Va,Vb,Result) :-
dot_acc(Va,Vb,0,Result).

なぜかというと、accumulatorをつかうとisの右引数のA
が具体的な数値になるから。


Lisp -> Lisper
Ruby -> Rubyist
Python -> Pythonista
Prolog -> Prologger?, Prologician? ???

こつこつ。

2009年7月5日日曜日

【LPN】4 Lists

リストになると俄然元気になる。

* 4 Lists
** 1 Lists
- リストだ!
- |はa special built-in operator。listsを分解する。
- |はUnificationとともに使える。
- variablesはunificationにてlistsもinstantiateで
きる。
- []はa special list。|で分解できない。
- 全てのlistsは、|の観点でいうと、[]で終端されてい
る。
- the anonymous variableは埋め草。
- そのbindingsは全て個別。
** 2 Member
- termsじゃなくてobjectsと言う表現がここで出始めて
いる。ここまでで言うと、terms + lists = objects
ということかな?
** 3 Recursing down Lists
- 入力にvariablesが使えるところがPrologの際立つと
ころ。
** 4 Exercise
- Exercise 4.1.
- 1. [a,b,c,d] = [a,[b,c,d]].
fail.
- 2. [a,b,c,d] = [a|[b,c,d]].
true.
- 3. [a,b,c,d] = [a,b,[c,d]].
fail.
- 4. [a,b,c,d] = [a,b|[c,d]].
true.
- 5. [a,b,c,d] = [a,b,c,[d]].
true.
- 6. [a,b,c,d] = [a,b,c|[d]].
true.
- 7. [a,b,c,d] = [a,b,c,d,[]].
fail.
- 8. [a,b,c,d] = [a,b,c,d|[]].
true.
- 9. [] = _.
true.
- 10. [] = [_].
fail.
- 11. [] = [_|[]].
fail.
- Exercise 4.2.
- 1. [1|[2,3,4]]
correct. 4 elements.
- 2. [1,2,3|[]]
correct. 3 elements.
- 3. [1|2,3,4]
incorrect.
- 4. [1|[2|[3|[4]]]]
correct. 4 elements.
- 5. [1,2,3,4|[]]
correct. 4 elements.
- 6. [[]|[]]
correct. 1 elements.
- 7. [[1,2]|4]
incorrect.
- 8. [[1,2],[3,4]|[5,6,7]]
correct. 5 elements.
- Exercise 4.3.
second(X,[_,X|_]).

すごくコンパクトな述語定義だ。Prologのパワー。

- Exercise 4.4.
swap12([X,Y|T],[Y,X|T]).

うーん。気持ちいい。

- Exercise 4.5.
listtran([],[]).
listtran([G|GT],[E|ET]) :-
tran(G,E),
listtran(GT,ET).

慣れてきた。
- Exercise 4.6.
twice([],[]).
twice([X|T1],[X,X|T2]) :- twice(T1,T2).

- Exercise 4.7.
割愛。
** 5 Practical Session

combine1([],[],[]).
combine1([H1|T1],[H2|T2],[H1,H2|T3]) :-
combine1(T1,T2,T3).

combine2([],[],[]).
combine2([H1|T1],[H2|T2],[[H1,H2]|T3]) :-
combine2(T1,T2,T3).

combine3([],[],[]).
combine3([H1|T1],[H2|T2],[j(H1,H2)|T3]) :-
combine3(T1,T2,T3).

こつこつ。

【LPN】3 Recursion


* 3 Recursion
** 1 Recursive Definitions
- stork: コウノトリ
- "Let's now consider both the declarative and
procedual meanings of the definition" ! 両方の
意味があるのか!
- 宣言的な意味は、PrologのKBの内容を論理的な言明
群と考えたとおりの字句通りのこと。
- 手続き的な意味は、そのKBに具体的なクエリをしたと
きの、具体的にPrologが実施するproof search処理の
こと。
- descendant: 子孫、末裔
** 2 Rule Ordering, Goal Ordering, and Termination
- Prologは、論理プログラミング言語として、完全で
はない。ここで完全ではない、というのは、宣言的
な記述をするだけであとは計算機がやってくれると
いうことができないということ。
- Prologでは、手続き的な側面も大事である。それは、
KBを上から下に探索するということ、サブゴールを
左から右に探索するということ、探索が失敗したと
きに直前の選択ポイントにバックトラックするとい
うこと。
- goalsの順番は重要。探索が止まらなくなる。
- left recursive rule: 左再帰ルール?
- headのfunctorはbodyではできるだけ遠くへ置け。
- 実践的に言うと、まず論理プログラミングの精神に
て問題を宣言的に記述する。それが終わったら、
Prologの手続き的観点からそれをチューンナップせ
よ。
** 3 Exercise
- Exercise 3.1.

descend(X,Y) :- child(X,Y).
descend(X,Y) :- descend(X,Z), descend(Z,Y).

まず、これは宣言的には正しそうだ。しかし手続き
的には止まらなくなりそうだ。止まらないケースを
シミュレーションしてみる。

descend(a,b).というクエリに対して、

まず、

descend(X,Y) :- child(X,Y).

に失敗するとする。すると、

descend(X,Y) :- descend(X,Z), descend(Z,Y).

を適用するので、サブゴールは、

descend(a,_G1), descend(_G1,b).

となる。左からやるのがルールなので、
descend(a,_G1)を探すが、

descend(X,Y) :- child(X,Y).

は失敗するとする。すると、

descend(a,_G2), descend(_G2,_G1).

の探索になり、これは終了しない探索になる。

- Exercise 3.2.

directlyIn(natasha,irina).
directlyIn(olga,natasha).
directlyIn(katarina,olga).
in(X,Y) :- directlyIn(X,Y).
in(X,Y) :- directlyIn(X,Z), in(Z,Y).

- Exercise 3.3.

travelFromTo(X,Y) :- directTrain(X,Y).
travelFromTo(X,Y) :- directTrain(Y,X).

travelFromTo(X,Y) :- directTrain(X,Z),travelFromTo(Z,Y).

- Exercise 3.4.

greater_than(succ(X),0).
greater_than(succ(X),succ(Y)) :- greater_than(X,Y).

- Exercise 3.5.

swap(leaf(X),leaf(Y)) :- =(X, Y).
swap(tree(LL,LR),tree(RL,RR)) :-
swap(LL,RR),
swap(LR,RL).

- Prologのfunctorを立案するときの頭の使い方はLisp
系言語の関数立案時とは全然違う。
- Lisp系のように再帰が便利とか重要とかいうレベルで
はなく、再帰が無いとプログラムにならない。書けな
い、じゃなくて、ならない。再帰はPrologの核であ
る。ウーン。うまい表現がみあたらない。
** 4 Practical Session
- 論理プログラミングは探検的プログミング手法には
向かないかもしれない。宣言的な記述を考えるのっ
て、何か頓知に近い気がする。慣れの問題なのかなぁ。


PAIPに通じる概念や観点が散見される。やはり古典的AIというのはProlog的なのだろうか。

こつこつ。

【LPN】2 Unification and Proof Search


* 2 Unification and Proof Search
- Unificationっていまいちつかめてないんだよなぁ。
やってることはわかるんだけど、なんでそれを
Unificationと呼ぶのというところが釈然としない。
PAIPでも引掛った記憶が。
- websterによると、、、
unify: to make into a unit or a coherent whole
あ、このa coherent wholeの方の意味のだったら納
得できる!
** 1 Unification
- PrologはUnificationするだけでなく、variablesに
ついてUnificationが成功するようなinstantiations
を実施してそれをプログラマに返却する。
- Unifyの定義。
- =/2の導入。=/2が、まんまUnifyの実装なんだ。

?- =(aka,aka).
true.

?- =(aka,hoge).
fail.

- お、Prologってinfixで書いてもいいんだ。

?- aka = aka.
true.

?- aka = hoge.
fail.

- Prologでのsymbolsはcharactersのこと。なので、an
atomはsymbolsから構成される。Common Lispとは違う。

- 一応Unifyの定義の構造を書いておく。
- Clause 1: a constantとa constantのunify。
- Clause 2: a variableとa termのunify。付随して、
a variableとa variableのunify。
- Clause 3: a complex termとa complex termの
unify。
- Clause 4: ufifyの定義は上記3つで必要十分であ
ることの言明。

- k(s(g),t(k)) = k(X,t(Y)).がunify可能かどうか。
- complex termsなのでClause 3。
- functorとarityは同じである。
- よって、argumentsがそれぞれunifyして
instansiationsに一貫性があるならばok。
- ひとつめのargument。
- 一方がa variableなのでClause 2。
- X = s(g)でinstatiationsにてunify。。
- ふたつめのarguments。
- complex termsなのでClause 3。
- functorとarityは同じである。
- よって、the argumentがunifyして
instantiationsに一貫性があるならok。
- the argument。
- 一方がa variableなのでClause 2。
- Y = kでinstatiationsにてunify。
- instansiationsに一貫性があるのでok。
- instansiationsに一貫性があるのでok。
- loves(X,X) = loves(marcellus,mia).がunify可能か
どうか。
- complex termsなのでClause 3。
- functorとarityは同じである。
- よって、argumentsがそれぞれunifyして
instantiationsに一貫性があるならok。
- ひとつめのargument。
- 一方がa variableなのでClause 2。
- X = marcelluslでinstantiationsにてunify。
- ふたつめのarugumet。
- 一方がa variableなのでClause 2。
- X = miaでinstantiationsにてunify。
- instatiationsに一貫性が無いのでunifyしない。

*** The occurs check

- Unificationは計算機科学の様々な分野で使われてい
て、徹底的に研究されつくしている。Unificationに
関するアルゴリズムもたくさんある。
- Prologはそれらstandard algorithmsを使用していな
い。
- standard alogrithmsでは、

father(X) = X.

はunifyしない。functorの数をかぞえるとすると、
左側の方が常に1多いと考えるから。
- Prologのlunificationはこれをunifyすると考える。
これはClause 2による。そしてXはfather(X)だから、
Xはfather(father(X))であり、さらに、Xは
father(father(father(X)))であり、という終りがな
い展開を実行する。
- 実行するとどうなるかは処理系による。out of
memoryになるものもある。やってみよう。

?- father(X) = X.
X = father(**).

?-

あり? なんか対処がなされているようだ
(SWI-prolog)。

- たぶん、father(**)は無限回のfatherの入れ子を表
わすのだろう。そうすれば、

father(father(**)) = father(**).

だ。これやってみよう。

?- father(father(**)) = father(**).
fail.

?-

なんですとぉ!

そうか。**がatomと認識されているんだな。

?- =(**,**).
true.

?- =(X,**).
X = **.

?-

読み書き不変性をもっていないのだと推測。

ちょっと遊んでみる。

?- father(Y) = X, mother(X) = Y .
Y = mother(father(**)),
X = father(mother(**)).

?- X = father(X), Y = father(Y), X = Y .
X = father(**),
Y = father(**).

?-

- standard alogorithmsはvariablesによる自己言及を
禁止している、ということかなぁ。それがoccurs
checkであると。
- Prologはoccurs checkをしない。それがshort cut。
そしてoptimisitc(楽観的)であるという所以。
- 安全性はプログラマが自分で確保せよ、と。
- Prologにもstandard unificationはあるよ。

?- unify_with_occurs_check(father(X),X).
fail.

?-

- しかしPrologが対象として無限そのものも扱える、と
いうのは凄いな。

*** Programming with unification
- horizontalとverticalの例。Unificationすごい。。。
パワフルだ。
- unificationを利用したプログラミングスタイルは、
対象領域の概念がhierarchical(階層制、階級制)で
あるときに有効である。

** 2 Proof Search
- a queryがsatisfiedである(満足する、充足する)か
どうか、a knowledge baseを探索することをproof
searchと呼ぶ。
- choice points。Prologは探索にあたって、他の選択
肢がありえるところをchoice pointsとして保持して
いる。ある枝にて探索が失敗した場合、choice
pointsに戻ってやり直すことをbacktrackingという。
- ;はPrologに、the last choice pointにバックトラッ
クして探索することを指示するものだ。
- Prologの探索木(search tree)の概念の説明。
- Prologのfactsは消費されない。

** 3 Exercises

- Exercise 2.1.
- 1. bread = bread.
unify.
- 2. 'Bread' = bread.
not unify.
- 3. 'bread' = bread.
unify.
- 4. Bread = bread.
unify.
instantiations: Bread = bread.
- 5. bread = sausage.
not unify.
- 6. food(bread) = bread.
not unify.
- 7. food(bread) = X.
unify.
instantiations: X = food(bread).
- 8. food(X) = food(bread).
unify.
instantiations: X = bread.
- 9. food(bread,X) = food(Y,sausage)
unify.
instantiations: X = sausage, Y = bread.
- 10. food(bread,X,beer) = food(Y,sausage,X).
not unify.
- 11. food(bread,X,beer) = food(Y,kahuna_burger).
not unify.
- 12. food(X) = X.
unify.
instantiations: X = food(**). (swi-prolog)
- 13. meal(food(bread),drink(beer)) = meal(X,Y).
unify.
instantiations: X = food(bread), Y = drink(beer).
- 14. meal(food(bread),X) = meal(X,drink(beer)).
not unify.

- Exercise 2.2.
- 1. ?- magic(house_elf).
fail.
- 2. ?- wizard(harry).
fail.
- 3. ?- magic(wizard).
fail.
- 4. ?- magic('McGonagall').
true.
(inner?)instantiations: X = 'McGonagall'.
- 5. ?- magic(Hermione).
Hermione = dobby;
Hermione = hermione;
Hermione = 'McGonagall';
Hermione = rita_skeeter.
true.

- Exercise 2.3.
- query
sentence(D1,N1,V,D2,N2).
- instantiations
a criminal eats a criminal
a criminal eats a 'big kahuna burger'
a criminal eats every criminal
a criminal eats every 'big kahuna burger'
a criminal likes a criminal
a criminal likes a 'big kahuna burger'
a criminal likes every criminal
a criminal likes every 'big kahuna burger'
a 'big kahuna burger' eats a criminal
a 'big kahuna burger' eats a 'big kahuna burger'
a 'big kahuna burger' eats every criminal
a 'big kahuna burger' eats every 'big kahuna burger'
a 'big kahuna burger' likes a criminal
a 'big kahuna burger' likes a 'big kahuna burger'
a 'big kahuna burger' likes every criminal
a 'big kahuna burger' likes every 'big kahuna burger'
every criminal eats a criminal
every criminal eats a 'big kahuna burger'
every criminal eats every criminal
every criminal eats every 'big kahuna burger'
every criminal likes a criminal
every criminal likes a 'big kahuna burger'
every criminal likes every criminal
every criminal likes every 'big kahuna burger'
every 'big kahuna burger' eats a criminal
every 'big kahuna burger' eats a 'big kahuna burger'
every 'big kahuna burger' eats every criminal
every 'big kahuna burger' eats every 'big kahuna burger'
every 'big kahuna burger' likes a criminal
every 'big kahuna burger' likes a 'big kahuna burger'
every 'big kahuna burger' likes every criminal
every 'big kahuna burger' likes every 'big kahuna burger'

- Exercise 2.4.

word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).

crossword(V1,V2,V3,H1,H2,H3) :-
word(V1,V11,V12,V13,V14,V15,V16,V17),
word(V2,V21,V22,V23,V24,V25,V26,V27),
word(V3,V31,V32,V33,V34,V35,V36,V37),
word(H1,H11,H12,H13,H14,H15,H16,H17),
word(H2,H21,H22,H23,H24,H25,H26,H27),
word(H3,H31,H32,H33,H34,H35,H36,H37),
V12 = H12, V14 = H22, V16 = H32,
V22 = H14, V24 = H24, V26 = H34,
V32 = H16, V34 = H26, V36 = H36.

** 4 Practical Session
- うーん。swi-prolog、notrace.でデバッグモードか
ら戻れない。

こつこつ。

【LPN】1: Facts, Rules, and Queries

あ、さきほどのエントリで、ペーパーバック版とオンライン版が内容は同一と書きましたが違いました。ペーパーバック版はもう一段改訂されています。


* 1 Facts, Rules, and Queries
** 1.1 Some simple examples
*** 1.1.1 Knowledge Base 1
- KB1はfactsのcollection。
- プロンプトから質問するとKB1の知識に基づいた
true/falseが返ってくる。これがPrologの使いかた。
*** 1.1.2 Knowledge Base 2
- 一度ロードしたKBのクリアの仕方がわからない。
- KB2はfactsとrulesを含む。
- ruleの形式。
head :- body
- KBに含まれたfactsとrulesとを、まとめてclausesと
呼ぶ。
- factの前半、すなわち、
listensToMusic(mia).
のlistensToMusicの部分を、predicate、procedure
と呼ぶ。factsはpredicatesの定義であるともいえる。
- factsは、body無しのrulesと見ることもできる。
*** 1.1.3 Knowledge Base 3
- ruleのbodyは、別名、goalとも呼ぶ。
- ","はand、";"はor。":-"はimplication。
*** 1.1.4 Knowledge Base 4
- queryにはvariableが使える。variableは大文字で書
く。
- variableを使うと、それにマッチするもの(unify可能
なもの)を探す。マッチするものがみつかったときに
は、"Prolog instantiates X to mia."や"Prolog
binds X to mia."などと言う。
- ";"を入力すると他のマッチを探して探索を継続する。
*** 1.1.5 Knowledge Base 5
- ruleの記述にvariableを使うことができる。これは
predicateの概念(関係)を表すものであり、general
statementと呼ぶ。
** 1.2 Prolog Syntax
- facts,rules,queriesを構成するものは何か。
- それはterms(語、語句、項)である。
- Prologでは、termsは4つに分類できる。atoms,
numbers, variables and complex terms。
- atomsとnumbersとをまとめてconstantsと呼ぶ。
- constantsとvariablesとによってPrologのsimple
termsが構成される。
- termsそれぞれの構成物はthe basic characters(or
symbols)である。termsはそれらのstringsである。
*** 1.2.1 Atoms
- アトムとして適格なのはつぎの3つ。
- 小文字ではじまるもの。(ただし記号はunder
scoreだけ)
butch
m_monroe2
- シングルクォートで囲まれたもの。
'Five_Dollar_Shake'
'hoge piyo 3 !'
- a string of special characters.
:-
@=
;
====>
- ここで3つ目の適用範囲がわからない。予約されたも
のに限るのか、記号のみからなる文字列はみなそう
なのか。
*** 1.2.2 Numbers
- Prologでも浮動小数点を扱えるが、Prologらしいプ
ログラムではあまり使わない。なのでこの本では割
愛するらしい。
- 整数は個数をかぞえるのに使うのでこの本でやる。
termsとしての例は次のとおり。
23
1001
0
-365
*** 1.2.3 Variables
- Atomsの第一の様式で、頭が大文字かアンダースコア
のもの。例は次のとおり。
X
Variable
_tag
List
- _は特別なもの。the anonymous variableという。無
名変数(変項)という訳かな? これはconstant
variablesに匹敵する用語かも。
*** 1.2.4 Complex terms
- complex termsは、atoms、numbers、variablesを部
品としてつくる。
- complex termsはfunctorをつかってつくる。様式は
次のとおり。

functor(arguments)

- functorはatomでないといけない。
- argumentsはargumentを,で区切って列記する。
argumentはtermならなんでもよい。
- ここでのfunctorは関手じゃないんだろうな。きっと。
precicatesを表わすatomのことかな。

- complex termsは、別名structuresとも言う。

- より複雑なcomplex termsは入れ子にすることによっ
てできる。例は次のとおり。

hide(X,father(father(father(butch))))

- argumentsの個数をそのcompex termsのarityと言う。
functor/nと表記することがある。

happy/1

- happy/1,happy/2のようにarityが違えば、functorの
atomが同じであっても別のpredicatesとPrologは認
識する。
** 1.3 Exercises
- Exercise 1.1
- 1. atom
- 2. variable
- 3. atom
- 4. variable
- 5. atom
- 6. atom
- 7. neither
- 8. atom
- 9. variable
- 10. atom
- Exercise 1.2
- 1. loves/2
- 2. atom
- 3. not term
- 4. boxer/1
- 5. and/2
- 6. and/2
- 7. not term
- 8. not term
- 9. not term
- 10. not term
- Exercise 1.3
- 7 clauses
- 3 facts
- 4 rules
- head person(X) goals man(X); woman(X)
- head loves(X,^) goals knows(Y,X)
- head father(Y,Z) goals man(Y), son(Z,Y)
- head father(Y,Z) goals man(Y),
daughter(Z,Y)
- Exercise 1.4
- 1. Butch is a killer.
killer(butch).
- 2. Mia and Marcellus are married.
married(mia, marcellus).
- 3. Zed is dead.
isDead(zed).
- 4. Marcellus kills everyone who gives Mia a
footmessage.
kills(marcellus,X) :- givesFootmassage(X,mia).
- 5. Mia loves everyone who is a good dancer.
loves(mia,X) :- isGoodDancer(X).
- 6. Jules eats anything that is nutritious or
tasty.
eats(jules,X) :- isNutritious(X); isTasty(X).
- Exercise 1.5
- 1. true.
- 2. false.
- 3. false.
- 4. false.
- 5. true.
- 6. Y = ron; Y = harry.
- 7. false.
** 1.4 Practical Session 1
- 問題なし。ただし、KBをクリアする方法は早く知り
たい。

PrologはPrologでおもしろそう。
こつこつ。

2009年7月4日土曜日

Prologに入門する

プログラミングGaucheを読了したので、SICPにいくのかと思いきや、Prologに入門することにする。目的は2つあって、

  • もうすぐPAIPでPrologのインタプリタを書くところに入るのですね。で、そこに書いてあることは書いてあるとおりにわかるんだけど、そもそもPrologがどんなものかを知らないので、Common Lispで書いたPrologインタプリタというのがどんなものなのか評価のしようがないのです。なのでPAIPをきっちり理解するためにPrologをやりたい。
  • あいかわらず数理論理学はあやふやなまま。FOLをきっちり抑えてからPrologをやろうと思っていたが、この際順番を逆にしてみる。

ということ。

テキストは、

Learn Prolog Now! (ペーパーバック オンライン

にする。(どちらも内容は同じ)

こつこつ。