論理プログラミングによる構造を表す関数 2014年1月27日

論理プログラミングによる構造を表す関数
2014年1月27日 Revision 1.00
古田秀和 (FURUTA Hidekazu)
背景
オブジェクト指向言語を特徴づけるものとして、(Microsoft .NET Framework のジェネリックコレクションのような)コレクション
( たとえばList、Dictionary)を容易に扱うことができることが考えられます。このようなコレクションのクラスがオブジェクト指向の
ライブラリにあって、オブジェクト指向言語から使えるようになっています。オブジェクト指向のプログラミングに現れるものの中
で、木のような再帰的な構造は再帰的なプログラムのプログラム上の位置を指定することによって実現されると考えることがで
きます。
関数プログラミングではそのような構造は関数で定義されています。関数プログラミングでオブジェクト指向のライブラリを利用
するため、構造を定義する方法を考察します。
H/Lシステム
V を 可 算 集 合、 C 、 F を 有 限 集 合 と し ま す ( V の 元 を 変 数、 C の 元 を 定 数、 F の 元 を 関 数 と 呼 び ま す )。
T = V  C  T   F  T  と 再 帰 的 に T を 定 義 し ま す ( T の 元 を 項 と 呼 び ま す。 こ こ で 集 合 X に 対 し て
*
2
X n = X  X    X ( n 個)、 X = 1  X  X   、  は 集合の直和、  は集合の直積、 1 は 1 個の元からなる
集合を表します)。 K = (T∖V) とおきます(これは項の論理積を表します)。 Q = (T∖V) K とおきます( Q の元を節と

呼び、節の最初の部分を頭部、2番目の部分を本体と呼びます)。 P = Q とおきます( P の元は Q の元の論理積を表し、
これを論理プログラムと呼ぶことにします)。
E = K  とおきます( E の元は K の元の論理和を表し、これを論理式と呼ぶことにします)。 s :VT を C 、 F の元を保存
するように s :EE に拡張することができます。このような定数と関数を保存する s :EE を代入と呼び、代入全体の集合
を S とおきます。
t T と q Q をと り ま す。 q の 変 数 を t に 含 まれな いものに置き換えたものを q' とおき、 q' の頭部を h 、 q' の本体を
b 1, b 2,  , bn とおきます( h, b iT∖V (i ) )。ここで括弧 [] は論理積の n 個の組を表すために使うことにします。
t q = equal(t, h ), b 1, b 2,  , b nK と定義します。 equal(t, h ) は t と h が一致することを表します。
p = q 1, q2,  , q mP に対して t p = t q1, t q2,  , t q mE と 定義します。ここで括弧 () は 論理和の
m 個 の 組 を 表 す た め に 使 う こ と に し ま す。 こ の 演 算  に よ っ て p :TE と み な す こ と が で き ま す。
対
し
て、 kip = t1p, t2p,  , tnp  、
e = k1, k2,  , k mE 、 ki = t1, t2,  , tnK に
e p = k 1p, k 2p,  , k mp  を選言標準形に変形したものと定義します。この演算  によって p :EE とみなす
ことができます。 t p p ( p が n 個)を t p と書くことにします。
n
k = t1, t2,  , tnK と p P に 対 し て、 s (k p n) の ど れかの連言が空とな る代入 s と 自然数 n が存在すると き
(k, p ) は成功、そうでないとき (k, p ) は失敗とします。
以下では 評価の順序について考えます。項 t = (f, (t1, t2,  , tn)) を t = f (t1, t2,  , tn) と書きます。 t1, t2,  , tn
の1 つが変数のと き、その変数を出力変数、項 t を出力変数をもつ項ということにします。節 q = (h, (t1, t2,  , tn)) を
h :-t1, t2,  , tn と書きます。
-1-
h と t1, t2,  , tn が出力変数をもつ項で、 h と tn の出力変数が一致するとき節 q を出力変数をもつ節ということにします。
以下では k = t1, t2,  , tnK のすべての項は出力変数をもつ項、 p P のすべての節は出力変数をもつ節の場合を
考えます。これをH/Lシ ステムと呼ぶことにします。(論理プログラミングによってHaskellのような純粋関数型言語を実現する
と いう意味でこのように呼ぶことにします。) (k, p ) が成功となる代入 s と自然数 n が存在するとき、 tn の出力変数 v の s
による値 s (v ) を評価の結果と呼ぶことにします。
評価空間
以 下 で は 評 価 の 順 序 に つ い て 考 え ま す。 k = t1, t2,  , tnK に 対 し て t1, t2,  , tn の 出 力 変 数 をそ れ ぞ れ
v1, v2,  , vn と おきます。代入の列 s1  s2    sn が存在して、任意の i に対して si(vi) は定数だけの式になって
いるものとします。この代入の列によって評価の順序が決まっていると考えます。
評価には 時間がかかるものとして、ある項の評価が行われる時間の範囲を評価期間と呼ぶことにします。 t1, t2,  , tn の評
価期間をそれぞれ z 1, z2,  , zn とおきます。全体の評価期間を z として z = z1 ≫ z2 ≫  ≫ zn と表すことにします。
これは 全体の評価期間が z1, z2,  , zn に分割されて、時間的な順序は z1, z2,  , zn という順になっていることを表しま
す。このとき評価期間には z1  z2    zn という順序  があるものとします。
t T と p = q 1, q 2,  , q nP に
対
し
て t p = t q 1, t q 2,  , t q n の
評
価
期
間 z は、
t q1, t q2,  , t q n の 評 価 期 間 をそ れ ぞ れ z1, z2,  , zn と す る と z = z1z2zn と表すこと にします。 z は
z1, z2,  , zn に分岐すると呼ぶことにします。 z1, z2,  , zn の時間的な順序は決まっていないものとします。
t T の評価期間を z0 と おきます。 Z0={z0} を t の評価空間と呼ぶことにします。 t p の評価期間が分割と分岐によって
z0=(z11≫z12≫≫z1n)(z21≫z22≫≫z2n)(zm1≫zm2≫≫zmn) と 表 さ れ た と し ま す。 こ の と き
t p の評価空間は Z1={z11, z12,  , z1n , z21, z22,  , z2n ,  , zm1, zm2,  , zmn} とします。この1回の変換で得ら
れる評価期間の集合 {z11, z12,  , z1n , z21, z22,  , z2n ,  , zm1, zm2,  , zmn} を評価平面、 z0 をその頂点と呼ぶ
ことにします。 t p の評価空間の各評価期間に対して、それを頂点とする評価平面に置き換えたものを t p
i
i+1
の評価空
間とします。
t p n の評価空間 Zn は  によって順序集合になります。 Zn の各評価期間に対して、それを評価の時間の範囲とする項が
対応しています。
ブレークポイント空間
C# のyield return文のようなものとして、項の後で出力変数を見ることができるようにすることができるものとします。このように
設定された項に対応する評価期間をブレークポイントと呼ぶことにします。ブレークポイントは評価期間と評価期間の間と考
えることもできます。ブレークポイントと評価期間の対を考えることによって、ブレークポイントと評価期間を同一視することもで
きます。
t p n のブレークポイント空間 Bn が評価空間と同様に定義できて、  によって順序集合になります。ブレークポイントの分
割、ブレークポイントの分岐、ブレークポイントの頂点とブレークポイント平面も同様に定義できます。ブレークポイント b Bn
に対して Bn(b )={x Bn|x b } とおきます。これを b のブレークポイントパスと呼ぶことにします。ブレークポイントパスは
 によって全順序集合になっています。
Bn(b )={b1 , b 2 ,  , bm}, b 1  b2    bm とし、 b1 , b 2 ,  , bm に対応する項をそれぞれ t1 , t2 ,  , tm とお
きます。 t1 , t2 ,  , tm の論理積を m=[t1 , t2 ,  , tm] と おき、 b1 , b 2 ,  , bm にそれぞれ 1 , 2 ,  , m の結果
( 最後の項の出力変数の値)を対応させる写像を  とおきます。写像  :BnE によってリストのような構造を構築すると考え
ることができます。(C#でyield returnを含む関数がリストを構築すると考えることができますがそれと同様に考えます。図はイ
メ ジ す )
-2-
メージです。)
b2

b n-1




1 
t1
2

n-1
z1
b1

zn-1
bn



n
tn-1
ズームインパス
この構造の構築が有限の時間で終わるとすると、さらにこの構造の時間的な変化を考えることができます。これをこの構造に
対する評価期間と考えることにより、複数の評価期間を持つ構造を考えることができます。(順序集合の直積として順序集合
B1B2Bm とを考えます。図はイメージです。)
B1B2Bm
b1b2bm

  m
1
B1B2Bm
  m
2
1
T1T2Tm

t1t2tm
2
T1T2Tm
あるブレークポイント b1 からその頂点 b2 、 b 2 の頂点 b 3 、のように次々に頂点をたどっていくと、最終的に全体の頂点 bm に
到達します。このとき b m , b m-1 ,  , b2 , b 1 の列をブレークポイント b 0 のズームインパスと呼ぶことにします。このズームイ
ンパス b1 , b 2 ,  , bm (添数を付け直します)は直積 B1B2Bm の元と考えることもできます。
ある論理プログラム p による( 0 回、 1 回、… n 回の)有限回のズームインによって得られるズームインパスの全体を ZPp と
おきます。ズームインパスに式を対応させる写像を考えることにより、木のような構造を表すことができます。ズームインパスに
は ブレークポイントが対応しているので、ズームインパスの構造を無視してブレークポイントと考えることにより、リストのような
構造を表すことができます。
H#/Lシステム
H/Lシステムのブレークポイントに対応する位置に、「 set (o, x ) 」という記述を書くことができるようにします。項 t1 と t2 の間
にブレークポイントがあるとき
, t1, set (o, e ), t2, 
と書くことができるようにします。 o はある定数で、これを論理Fオブジェクトと呼ぶことにします。(これはオブジェクト指向的な
オブジェクトを表すものと考えることができます。) e は式で、この位置のブレークポイントにこの式 e が対応することを表しま
す。この記述によって論理Fオブジェクトを構築することができます。このような関数を論理Fコンストラクタと呼ぶことにします。
(図はイメージです。)
b1

b2

b n-1


set(o, e



set(o, en-1
1

2

n-1

e1
1)
t1
en-1
bn
)

n
tn-1
論理Fオブジェクトを使うために「 get (o, e ) 」という記述も書くことができるようにします。(図はイメージです。)
b1

b2

bn-1


get(o, e



get(o, en-1
1

2

n-1

論
e1
1)
t1
構築
en-1
bn
)
tn-1
論

n
ブジ
使う
-3-
論理Fコンストラクタ f1(o1, e1) で構築した論理Fオブジェクトを f2(o 1, e2) で使うとき
, f1(o 1, e 1), set (o 2, e'), f2(o 1, e 2), 
のように書くことができるものとします。この記述によって、論理Fオブジェクトの時間的な変化を表すことができます。順序集
合の直積を考えることにより論理Fオブジェクトは1つにすることができます。
このようにH/Lシステムを拡張すると、リストのような構造を表すことができます。また、setがプログラム上の位置を記録できるも
の、getがプログラム上の位置を参照できるものと考えることにより、木のような構造を表すことができます。このように拡張した
ものをH# /Lシステムと呼ぶことにします。
結論
論理プログラミングにプログラム上の位置を記録する機能を追加することにより、ある再帰的な構造を表すことができます。
今後の課題
プログラム上の位置を記録する方法については、論理Fオブジェクトが単に定数と考える方法では実現できないかもしれない
ので、さらに詳しく考えていく必要があります。
オブジェクト指向言語の関数型言語的機能を実現するため、関数型言語でも同様の構造を表す方法についても考える必要
があります。
参考文献
Haskell
本物のプログラマはHaskellを使う
http://itpro.nikkeibp.co.jp/article/COLUMN/20060915/248215/
F#
F#入門
http://winterradish.web.fc2.com/
Prolog
お気楽 Prolog プログラミング入門
http://www.geocities.jp/m_hiroi/prolog/
履歴
2014年1月27日 Revision 1.00
-4-