型と素性

English version

目次


素性構造

素性構造(feature structure, FS)とは, 各ノード,各エッジに名前のついた有向グラフのことです. ノードについた名前は型(type)と呼ばれ, エッジについた名前は素性(feature)と呼ばれます. 各ノードからどのような素性のエッジが出るか(以下では, 「各型がどのような素性を持つか」という言い方をします)というのは, そのノードの型から一意に決まります. 各素性の先はまた素性構造になっているので,素性構造とは, 型と素性からなる再帰的なデータ構造と言うことができます.

図3.1 素性構造の例
       名前
     −−−−→ダンスインザダーク
    |     系統
→競走馬−−−−−→Hail to Reason
    |\  父          系統 ↑
    |  −−→種牡馬−−−−
    |          | 名前
    |           −−−→サンデーサイレンス
    | 母            名前
     −−→繁殖牝馬−−−−→ダンシングキイ
              | 系統
               −−−→Northern Dancer

一番左の矢印で指されているノードは,根(root)と呼ばれる特別なノードで, どんな素性構造にも必ず一つ存在するノードです. また,型'Hail to Reason'がついているノードは, 二つのエッジの先となっています.このような構造を, 構造共有(後述)と呼びます.

このようなグラフをいちいち書くのは面倒なので, 一般に次のようなAVM(Attribute-Value Matrix) で記述します.

図3.2 素性構造のAVM表記の例
|~競走馬                        ~|
| 名前:ダンスインザダーク        |
| 系統:$1 Hail to Reason         |
|    |~種牡馬                 ~| |
| 父:| 名前:サンデーサイレンス | |
|    |_系統:$1                _| |
|    |~繁殖牝馬            ~|    |
| 母:| 名前:ダンシングキイ  |    |
|_   |_系統:Northern Dancer_|   _|

これは,初めの図と同じ構造を表しています. 角かっこで囲まれた部分が,素性構造です. かっこ内の左上に書かれているものが,その素性構造の根の型で,その下に, それぞれの素性と,その素性の先の素性構造を書きます. 構造共有は,ダグ(上の図では, "$1")で表します(詳しくは後述).LiLFeSが素性構造を画面に表示する時も, この記述方法を使います.

LiLFeSでは,各素性の先に来る素性構造の根の型を指定することができます. 例えば,上の例では, 素性'父'の先のノードは型'種牡馬'であるとすれば, '競走馬'や'Hail to Reason'が来ることができなくなります.


型階層

(type)は,階層構造を持っています. 例えば,三角形の種類について, 次のような階層構造を作ることができます.

図3.3 型階層の例
正三角形  直角二等辺三角形
   \      /         \
   二等辺三角形    直角三角形
          \        /
             三角形
               |
              bot

線で結ばれた関係はsupertype-subtypeの関係と呼ばれ,上の図では, 下側がsupertype,上側がsubtypeになっています. 全ての型('bot'を除く)は, 必ず一つ以上のsupertypeを持ちます. supertypeはsubtypeを汎化したもの, subtypeはsupertypeを特化したものと呼ばれ,上の例では, supertypeの概念を特殊化した概念が,subtypeになるようにしています. 型階層は,このような特殊化・一般化の関係を記述するのに使うのが一般的です. また,supertypeを遡っていった型,subtypeをたどっていった型も, それぞれsupertype, subtypeと呼ばれます. 上の図の一番下にある型 'bot'(bottom)は, LiLFeSに組み込みの型で,全ての型のsupertypeとなる型です.


型の単一化

型と型との間の演算として, 単一化(unification)が定義されます. 直観的には,上の図のような型階層の中で, 二つの型の共通のsubtypeのうち, いちばん一般的な型を見つける操作になります. このような型を,LUB(Least Upper Bound)と呼びます.

二つの型をそれぞれX,Yとすると,単一化は,LiLFeSでは

X = Y
で表されます(=は中おきの述語).例えば, 上記の三角形の例を使うと,
> ?- X = 三角形, X = 二等辺三角形.
X: 二等辺三角形
> ?- X = 二等辺三角形, X = 直角三角形.
X: 直角二等辺三角形
> ?- X = 正三角形, X = 直角三角形.
no
となります.共通のsubtypeが無い時は,失敗します.また, 'bot'は全ての型のsupertypeなので, どんな型Xとの単一化も成功し, 結果はXになります.

LiLFeSの型階層では, 単一化の結果(LUB)は一意に定まらなければならないという制約があります. つまり,二つの型の共通のsubtypeが複数あって, しかもその中にsupertype-subtypeの関係に無い型の組があるような階層構造は, 定義できないということです.例えば, 上の例で'二等辺三角形'と'直角三角形' とを直接のsupertypeとする新たな型Aを定義しようとすると, エラーになります.このような制限があるため, PROLOGの述語による表現より弱い表現になるわけですが,そのおかげで, 型の単一化の処理は高速に行なわれます.


素性

各型は,素性(feature)を持つことができます. supertypeが素性を持っている場合はその素性を受け継ぎ,それに加えて, 新たな素性を付け加えることができます. 複数のsupertypeが存在する時には同じ素性を受け継ぐ可能性がありますが, その様な場合は,一つにまとめられます.LiLFeSでは, 同じ名前の素性を2度以上定義することはできないという制約があります.

例として,次のような型階層を考えます.角かっこ内が, その型で新たに定義される素性です.

表3.4 素性の例
ストレート[最小の数]  フラッシュ[スート]
              \          /
               ポーカーの役
                    |
                   bot

ここで,'ストレート'と'フラッシュ'をsupertypeとする型 'ストレートフラッシュ'を定義すると,それは, '最小の数'と'スート'という2つの素性を初めから持っていることになります. もし型'ポーカーの役'に何らかの素性Aがあったとすると, それは'ストレート'と'フラッシュ'にも受け継がれ, さらに'ストレートフラッシュ'には,両方の直接のsupertypeから, 同じ素性Aを受け継ぐことになります.このときは, 素性Aは一つに合併され,結局, 'ストレートフラッシュ'は3つの素性を持つようになります.


素性構造の単一化

素性構造の単一化は,まず,根の型を単一化することから始まります. それに成功したら,つぎに,各素性をたどっていき, その先の素性構造を単一化します.この操作を再帰的に行ない, 全てのノードで単一化が成功すると, 全体の素性構造の単一化が成功したことになります.

ポーカーの役の例を使って, 次のような2つの素性構造の単一化を考えてみます.

|~ストレート ~|
|_最小の数:10_|
|~フラッシュ     ~|
|_スート:スペード_|
まず,根の型'ストレート'と'フラッシュ'とを単一化します. これの結果は'ストレートフラッシュ'になるので, それぞれの素性構造は,次のようになります.
|~ストレートフラッシュ~|
| 最小の数:10          |
|_スート:bot          _|
|~ストレートフラッシュ~|
| 最小の数:bot         |
|_スート:スペード     _|
次に,各素性について,その先の素性構造を単一化します. 素性'最小の数'の素性構造は型'10'になり, 素性'スート'の素性構造は型'スペード'になります.そして, 全てのノードの単一化が成功したので,次のような結果が得られます.
|~ストレートフラッシュ~|
| 最小の数:10          |
|_スート:スペード     _|


構造共有

素性構造は,一般的なグラフ構造を有することができます.木構造との違いは, 複数のエッジの先が一つのノードになる可能性があるということです. このような構造を, 構造共有(structure sharing)と呼びます. 初めの例では,型'Hail to Reason'のノードで, 構造共有が起きています.AVMで表現する時は, 構造共有が起きているノードを根とする素性構造に対するAVMの前に, ダグ(dag) $x(xは任意の数字)を書き, 構造共有が起きている他のノードに同じダグを書いて表します.また, 構造共有されているノード以降の素性構造はどこか1箇所だけで書くことにし, 他のところでは省略することにすれば,ループを含む素性構造も, 有限の記述で表現できます.

構造共有を含む素性構造の単一化は, 前節の方法がそのまま適用できます.ただ, 構造共有が起きているという情報も,単一化されます. 例えば,次のような2つの素性構造を単一化する場合,

|~example ~|
| A:$1 bot |
| B:$1     |
|_C:bot   _|
|~example ~|
| A:bot    |
| B:$2 bot |
|_C:$2    _|
素性'A'を単一化した時, 素性'A'と素性'B'の先は構造共有されているという情報が, 下の構造にも伝えられます.同様に, 下の構造では素性'B'と素性'C'とが構造共有されているので, それが上の素性構造にも伝えられます.結局, 単一化の結果は次のようになります.
|~example ~|
| A:$1 bot |
| B:$1     |
|_C:$1    _|


その他

LiLFeSでは,PROLOGと同様に,リストを扱うことができます.

> ?- X = [1, 2, 3].
X: < 1, 2, 3 >

リストは,実際には素性構造になっています. リストの型は'list'で, 直接のsubtypeに'cons'と'nil'という型を持ちます. また,'cons'は, 'hd'と'tl'という素性を持ちます. Lispの言葉を借りれば,'hd'は'car'にあたり, 'tl'は'cdr'にあたります.従って, 上の例のリストは,次のような素性構造であるということになります.

|~cons                ~|
| hd:1                 |
|    |~cons         ~| |
|    | hd:2          | |
| tl:|    |~cons  ~| | |
|    | tl:| hd:3   | | |
|_   |_   |_tl:nil_|_|_|

素性構造ですから,構造共有も表現できます.例えば,次のようにして, 1と2が交互に無限に続く列を表現することができます.

> ?- X = [1, 2 | X].
X: [$1] < 1, 2 | [$1] ... >

LiLFeSでは,述語や素性名なども,全て素性構造として扱われています.


2章 インストールと実行 4章 文法
目次 LiLFeSドキュメント LiLFeSホームページ 辻井研究室