第1章 ルールの記法と意味
1. 問題からルールを記述する
ETプログラミングでは、問題を正しく簡単化する「ルール」を記述していくことで与えられた問題を解 決する。 例えば、家族関係を調べる問題を考える。その前提として次の4つの知識が与えられていたと する。
(1) 雄介の父親は太郎である。
(2) 優香の父親は太郎である。
(3) 太郎の父親は茂太である。
(4) 茂太の父親は熊吉である。
父親と子どもの関係を満たす組はこの4つ以外にはないとする。このような文をルールや節の中で表現 するためにアトムを導入する。 アトムは、これ以上分割できない最小単位の文(原子文)のことであ り、述語と引数の並びで表す。 その書き方はある程度任意性があるので、書き方をあらかじめ約束する 必要がる。例えば、「Xの父親はYである」という原子文を(father X Y) というアトムで表すと約束す る。 このとき、「雄介の父親は太郎である」という原子文は、述語father、引数yusuke、taroを用いて
(father yusuke taro)と書ける。
このようなアトムを用いて、家族関係を調べるためのいくつかのルールを書くことを考える。(1)〜(4) の父子関係から、fatherアトムを用いて以下のようなルールを書くことができる。 *Xや*Yなど、*ではじ まる文字列はETの変数である。
(1) (father *X *Y), {(== *X yusuke)} ==> (= *Y taro).
(2) (father *X *Y), {(== *X yuka)} ==> (= *Y taro).
(3) (father *X *Y), {(== *X taro)} ==> (= *Y shigeta).
(4) (father *X *Y), {(== *X shigeta)} ==> (= *Y kumakichi).
これらのルールは、それぞれ次のことを意味する。
(1) (father *X *Y)アトムは、*X がyusukeのとき、(= *Y taro) に置き換えることができる。
(2) (father *X *Y)アトムは、*X がyukaのとき、(= *Y taro) に置き換えることができる。
(3) (father *X *Y)アトムは、*X がtaroのとき、(= *Y shigeta) に置き換えることができる。
(4) (father *X *Y)アトムは、*X がshigetaのとき、(= *Y kumakichi) に置き換えることができ る。
たとえば(1)は(father yusuke <対象1>)を(= <対象1> taro)に置き換えるもので、両者は最初の4つ の知識のもとで等価である。
2.ルールの記法と意味 2.1 簡単なルール
本書で採用しているルールの表現をR (Rewrite) 式と呼ぶ(ルールの表現にはR式のほかにS式があ る)。 R式は、ある問題を別の問題に置き換える方法を直感的にわかりやすく表現している。 多くの場 合R式は、
〈アトム〉, {〈アトム〉, ・・・, 〈アトム〉} ==> 〈アトム〉, ・・・ ,〈アトム〉.
という形をしている。ルールの形は、アトムとアトムが並んでいるときにはコンマで区切り、最後はピリ オドで終わるという形になっている。 中括弧の中においても、いくつかのアトムがコンマで区切られて 並べられている。
前節の父子関係を表すルールはこのルールの特別な場合で、
〈アトム1〉, {〈アトム2〉} ==> 〈アトム3〉.
という形をしている。このルールは、質問が〈アトム1〉にマッチし、〈アトム2〉の条件を満たしてい るなら、〈アトム1〉を〈アトム3〉に置き換えてもよいという意味を持っている。
置き換えようとするアトム(ここでは〈アトム1〉)を、ヘッド(Head)という。ヘッドは1個のアトム であり、矢印の左にある。この ヘッドは、質問のパターンとヘッドのパターンの照合から、ルールが適 用可能であるかどうかを検査するという役割を持つ。 中括弧で囲まれたアトム列(ここでは〈アトム2〉
だけの列)は、条件列(Cond)という。条件列は一般に0個以上のアトム列である。 条件列中のアトムが 0個の場合は、中括弧とその前のコンマを省略でき、
〈アトム〉 ==> 〈アトム〉, ・・・ ,〈アトム〉.
という形でルールを書くことができる。例えば、「yusukeの父親は*Yである」ということをアトムで表現 すると、
(father yusuke *Y)
となり、yusukeの父親はtaroであるので、
(father yusuke *Y) ==> (= *Y taro).
というルールを記述することができる(つまり最初の4つのルールは、いずれも条件列なしで書くことが できるのである)。
アトム列同士を矢印(==>)でつなぐことは、アトム列を別のアトム列に置き換えることを意味する。
ここでは、アトム1をアトム3のパターンに置き換えることを意味している。矢印以降にあるアトム列を ボディ(Body)という。
ボディ中の個々のアトム(ここでは〈アトム3〉)を置き換えアトムという。ボディは0個以上の置き換 えアトムの列である。 ルールは、
ヘッド、条件列、==> 、ボディ(置き換えアトム列).
で構成されていると言える。
2.2 複数ボディルール
先程記述した(1)〜(4)のルールは、子どもがわかっている時に父親を求めるルールであった。 これらの 4つの父子のペアを1つのルールで扱うには、次のルールを書けばよい。
(father *X *Y) ==> (= *X yusuke), (= *Y taro);
==> (= *X yuka), (= *Y taro);
==> (= *X taro), (= *Y shigeta);
==> (= *X shigeta), (= *Y kumakichi).
これは、「*X の父親は *Y である」という条件を、
(1) *X がyusukeで *Y がtaroの場合、
(2) *X がyukaで *Y がtaroの場合、
(3) *X がtaroで *Y がshigetaの場合、
(4) *X がshigetaで *Y がkumakichiの場合、
の4つの場合に置き換えることができるという意味のルールである。このルールは、fatherの2つの引数 が何であっても適用できるので、前の4つのルールの各々よりも一般的なルールだといえる。
このように、ある質問について複数の置き換えパターンが考えられる場合、例えば、次の形のルールを 書くことができる。
〈アトム〉, {〈アトム〉,・・・,〈アトム〉} ==> 〈アトム〉,・・・,〈アトム〉;
==> ・・・ ;
==> 〈アトム〉,・・・,〈アトム〉.
このような複数個のボディを持つルールを複数ボディルールといい、ヘッドのアトムが条件列を満たした とき、複数のアトム列に置き換えることができるのを意味している。
複数ボディを表すには、1番目のボディの末尾に;(セミコロン)を記述し、 ==> ボディ; という形で 書く。最後のボディを書くときは、末尾を;の代わりに.(ピリオド)で終わる。
2.3 実行列を持つルール
これまでのルールは、ヘッドをボディのアトム列に置き換えるものであった。この「置き換え」の操作と 並んで重要なのが、代入の操作である。 代入の操作は、ルールのボディ部の先頭に実行列を書くことに よって達成される。
たとえば、ボディアトムが1つからなるルールの場合、
〈アトム〉 ==> {〈アトム〉, ・・・ ,〈アトム〉},〈アトム〉, ・・・ ,〈アトム〉.
のようなルールが考えられる。ボディ(矢印の右)のうち中括弧で囲まれたアトム列が、実行列(Exec部) である。中括弧の後のアトムを置き換えアトムというが、それが存在しない場合には、
〈アトム〉 ==> {〈アトム〉, ・・・ ,〈アトム〉}.
という形になる。家族関係を示すルールにおいて、(= *X *Y) というアトムは、組み込み述語で処理され るので、先程のルールの他に、
(= *X *Y) ==> {(= *X *Y)}.
というルールが必要になる。組み込み述語を導入する場合には、実行列を用いてルールを記述するという ことを意識しておけばよい。 実行列の必要性や詳しい意味は、テキストの進行につれ適宜説明する。
ETGUIにおけるアスタリスク(*)と空白に関すること
変数であることを表すには、半角のアスタリスクを付ける必要がある。ルールはアトムで構成 されるが、アトムはS式と呼ばれる記法で書かれている。S式は一般に、定数と変数と括弧で構成 されるようなひとまとまりの式である。定数には、シンボル、数、文字、文字列などがある。シ ンボルと変数はよく似ている。例えば、appleはシンボルであり、*appleは変数である。
シンボルと区別するために、変数の先頭には* が付けられる。シンボル(演算子もその一種)や 変数が並んだ場合には、それらを空白(半角で一文字以上)で区切る必要がある。空白を空けない と一つの対象(シンボルまたは変数)としてみなされてしまうので注意すること。
演算子の記法に関すること
ルール中の計算式は、演算子を先頭につける「前置記法」で表現する。数学で数式を書く場合 には、演算子を間に置く中置記法で記述することが多いが、 ETではうっかり中置記法でルールを 記述するとエラーとなるので注意が必要である。
前置記法・・・(= *X yuka)
中置記法・・・(*X = yuka)