単一化(unification)


単一化の定義

この節の定義等の多くは[1]から引用しています。

V を可算無限個の変数の集合、F を関数記号の集合とします。 V, F から構成される項の集合 T(F, V) を以下の条件を満たす最小の集合と定義します。
  1. x∈V ⇒ x∈T(F, V)
  2. f∈F, t1, ..., tn∈T(F, V) ⇒ f(t1, ..., tn)∈T(F, V)
関数記号 f ごとに、f がとりうるパラメータの個数 n があらかじめ定められているものとします。 この n を f の項数といいます。 (以下で、T(F, V) を T と書きます。) 項 x, y が一致することを x≡y と書きます。

代入

V から T への写像 σ でD(σ)={x∈V|xσ≠x} が有限なものを代入といいます。 ここで D(σ) を σ の定義域といいます。 項 t に含まれる変数の集合を V(t) と書きます。 代入 σ は D(σ)={x1, ..., xn} の各 xi と xiσ (写像 σ で xi に対応する T の元) との対応の集合 {x1σ/x1, ..., xnσ/xn} で表すことができます。

代入の拡張

代入 σ の定義域を T へと拡張した写像 σ~: T→T を次のように定義します。
  1. x∈V のとき、xσ~≡xσ
  2. x≡f(x1, ..., xn) のとき、 f(x1, ..., xn)σ~ ≡ f(x1σ~, ..., xnσ~)
また、D(σ~)=D(σ) とします。 σ~ と σ を同一視することがあります。 { } で表される代入を拡張した写像は恒等写像となります。

単一化代入

項 s, t に対し、sθ≡tθ となる代入 θ を単一化代入(unifier)といいます。 sθ≡tθ となる代入 θ が存在するとき、項 s, t は単一化可能(unifiable)であるといいます。

最も一般的な単一化代入

代入 θ が2つの項 x, y の単一化代入で、任意の x, y の単一化代入 μ に対して、 μ = θλ となる代入 λ が存在するとき、 θ は最も一般的な単一化代入(most general unifier, mgu)であるといいます。 (θλ は x に (xθ)λ を対応させる写像です。)

単一化アルゴリズム

occur(x, u)=True(xがuの真部分項)
False(xがuの真部分項でない)
と定義します。 単一化アルゴリズム UNIFY を以下のように定義します。
UNIFY(s, t) = 
    begin
        θ := {}
        if s∈V ∨ t∈V then
            begin [変数をx, 他の項をuとする]
                if x≡u then unifiable := True
                else if occur(x, u) then unifiable := False
                else <unifiable, θ> := <True, {u/x}>
            end
        else if s∈K ∨ t∈K then
            begin
                if s≡t then unifiable := True
                else unifiable := False
            end
        else
            begin [t≡f(t1, ..., tnn), s≡g(s11,...,sm)とする]
                if ¬f≡g ∨ m≠n then unifiable := False
                else
                    begin
                        unifiable := True
                        for k = 1,...,n while unifiable
                            begin
                                <unifiable, σ> := UNIFY(tkθ, skθ)
                                if unifiable then θ := θσ
                            end
                    end
            end
        return <unifiable, θ>
    end
アルゴリズム UNIFY について以下のことが成り立ちます。 以下の節でこの証明と上のアルゴリズムをプログラミング言語を使って記述する方法について考えます。

単一化アルゴリズム

項の構成に関する帰納法

f∈F のとき f の項数を a(f) と書きます。 f∈F のとき I(f) = {f(x1, …, xn)|n =a(f), x1, …, xn∈T}、 I = ∪f∈FI(f) と書きます。 述語 p(x) が
  1. p(x) (x∈V のとき)
  2. p(x1), …, p(xn) ⇒ p(f(x1, …, xn)) (x∈I, x≡f(x1, …, xn) のとき)
をみたすならば任意の項 x に対して p(x) が成り立ちます。

不一致集合

x≡y は次のように定義されます。
  1. x∈V, y∈V, x=y のとき、x≡y
  2. x1≡y1, …, xn≡yn のとき、 f(x1, …, xn) ≡ f(y1, …, yn)
x≡y でないとき、x, y の不一致集合を次のように定義します。
  1. x≡f(x1, …, xn), y≡f(y1, …, yn) のとき、xi≡yi ではない i をとって xi, yi の不一致集合を x, y の不一致集合とする。
  2. それ以外のとき、{x, y} を x, y の不一致集合とする。

Mguの性質

2つの項の組 <x1, …, xn>, <y1, …, yn> に対して 代入 θ が x1θ≡y1θ, …, xnθ≡ynθ をみたすとき、 項の組 <x1, …, xn>, <y1, …, yn> の単一化代入といいます。 代入 θ が項の組 <x1, …, xn>, <y1, …, yn> の単一化代入で、 任意の <x1, …, xn>, <y1, …, yn> の単一化代入 μ に対して、 μ = θλ となる代入 λ が存在するとき、 θ は <x1, …, xn>, <y1, …, yn> の mgu であるといいます。 mgu について以下のことが成り立ちます。
  1. x∈V, y∈V, x=y のとき θ=1 は x, y の mgu となります。
    証明: θ は単一化代入になっています。 μ が単一化代入のとき、θμ = μ となります。
  2. x∈V, y∈V, x≠y のとき θ={y/x}, θ={x/y} は x, y の mgu となります。
    証明: θ={y/x} のとき: θ は単一化代入になっています。 μ が単一化代入のとき、 x{y/x}μ ≡ yμ ≡ xμ、 v∈D(μ)-{x} のとき v{y/x}μ ≡ vμ となります。 したがって任意の v∈D(μ)∪{x} に対して vθ≡v{y/x}μ≡vμ となるので θμ = μ となります。 θ={x/y} のときも同様です。
  3. x∈V, y∈I, {x}∩V(y)=φ のとき θ={y/x} は x, y の mgu となります。
    証明は 2 と同様です。
  4. x∈I, y∈I, x=y のとき θ=1 は x, y の mgu となります。
    証明は 1 と同様です。
  5. σ1 が x1, y1 の mgu、 σ2 が x2σ1, y2σ1 の mgu のとき θ=σ1σ2 は <x1, x2>, <y1, y2> の mgu となります。
    証明: x1θ≡y1θ, x2θ≡y2θ となります。 代入 μ が x1μ≡y1μ, x2μ≡y2μ をみたすとき、 μ=σ1λ1 をみたす代入 λ1 が存在します。 x2σ1λ1≡y2σ1λ1 となるので、 λ12λ2 をみたす代入 λ2 が存在します。 μ=θλ2 となります。
  6. x∈I, y∈I, x=f(x1, …, xn), y=f(y1, …, yn), 代入 σ1=1, …, σn+1 が存在して 任意の i = 1, …, n に対して σi+1 が xiσ1…σi, yiσ1…σi の mgu となるとき、θ=σi+1 は x, y の mgu となります。
    証明は 4, 5 からわかります。
単一化可能性について以下のことが成り立ちます。
  1. x∈V, y∈I, x∈V(y) のとき x, y は単一化可能ではありません。
    証明: θ を代入とします。 y≡f(…x…) とすると、yθ≡f(…xθ…) となるので、xθ≡yθ となる代入 θ は存在しません。
  2. x∈I, y∈I, x≡f(…), y≡g(…), f≠g のとき x, y は単一化可能ではありません。
    証明: θ を代入とします。 xθ≡f(…), yθ≡g(…) となるので、このような代入 θ は存在しません。

単一化アルゴリズム(1)

項 x, y に対して代入 θ0=1, θ1, θ2, … を次のように定義します。 ([2, 4]を参照)
  1. n≡yθn のときは成功。
  2. n≡yθn ではなく xθn, yθn の不一致集合 {u, v} が v∈V, u∈V のとき θn+1n{u/v} とする。
  3. n≡yθn ではなく xθn, yθn の不一致集合 {u, v} が v∈V, u∈I で v が V(u) に含まれないとき θn+1n{u/v} とする。
  4. それ以外のときは失敗。
n+1, yθn+1 の変数の個数は xθn, yθn の変数の個数より少ないので、 x, y の変数の個数を m とすると、xθm, yθm (がもしあれば) の変数の個数は 0 となり、このときは 1, 4 の場合しか起こらないので、m 以下で成功または失敗となります。

単一化アルゴリズム(2)

mgu の性質から、 項 x, y から代入 θ を求めるアルゴリズム unify2(x, y, θ) を次のように定義することができます。 このアルゴリズムは前節のアルゴリズム UNIFY と同様のものになります。
  1. x∈V, y∈V, x=y のとき成功。(θ=1)
  2. x∈V, y∈V, x≠y のとき成功。(θ={y/x} または θ={x/y})
  3. x∈V, y∈I, {x}∩V(y)=φ のとき成功。(θ={y/x})
  4. x∈I, y∈V, {y}∩V(x)=φ のとき成功。(θ={x/y})
  5. x∈I, y∈I, x=f(x1, …, xn), y=f(y1, …, yn) のとき σ1=1 として i = 1, …, n に対して unify2(xiσ1…σi, yiσ1…σi, σi+1) を実行してすべて成功のとき成功。(θ=σn+1)
  6. それ以外のときは失敗。
mgu の性質から、上のアルゴリズムの結果が成功のとき、θ は x, y の mgu となります。 また、単一化可能性の性質から、結果が失敗のとき x, y は単一化可能ではありません。 (項の構成に関する帰納法により) 5 の場合にどの i を選んでも 5 の場合だけが続くことはありません。 したがって (x, y の変数の個数に関する帰納法により) 単一化アルゴリズム(1)と同様に有限の回数で成功または失敗となります。

単一化アルゴリズム(1), (2)の関係

単一化アルゴリズム(1)は次の unify(x, y, μ, θ) のように表すことができます。 subterm(x, y, s, t) は x, y の共通の部分項 s, t を求めるものです。 subterm(x, y, s, t) ∧ ¬s_equal(s, t) は x, y の不一致集合 {s, t} を求めるものです。 Nn = {1, …, n} と書きます。
subterm(x, y, s, t) x=s ∧ y=t
x∈I(f) ∧ y∈I(f) ∧ n=a(f) ∧ x≡f(x1, …, xn) ∧ y≡f(y1, …, yn) ∧ ∃i∈Nnsubterm(xi, yi, s, t)
s_equal(x, y) x∈V ∧ y∈V ∧ x=y
x∈I(f) ∧ y∈I(f)
s_unify(x, y, θ) x∈V ∧ y∈V ∧ (θ={y/x} ∨ θ={x/y})
x∈V ∧ y∈I ∧ ¬(x∈V(y)) ∧ θ={y/x}
x∈I ∧ y∈V ∧ ¬(y∈V(x)) ∧ θ={x/y}
unify(x, y, μ, θ) (subterm(xμ, yμ, s, t) ⇒ s_equal(s, t)) ∧ θ=μ
subterm(xμ, yμ, s, t) ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
このアルゴリズムの中で、∃i∈Nnsubterm(xi, yi, s, t) は、i=1 から順に実行するものとします。 また、∨で結合した条件は上から順に実行するものとします。 以下のように unify(x, y, 1, θ) ⇔ unify2(x, y, θ) ということがわかります。
unify(x, y, μ, θ) (subterm(xμ, yμ, s, t) ⇒ s_equal(s, t)) ∧ θ=μ
xμ=s ∧ yμ=t ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ ∃i∈Nnsubterm(xi, yi, s, t) ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
(subterm(xμ, yμ, s, t) ⇒ s_equal(s, t)) ∧ θ=μ
xμ=s ∧ yμ=t ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ subterm(x1, y1, s, t) ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ subterm(xn, yn, s, t) ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
一度実行した条件は、次の呼び出しでは s_equal(s, t) が成立します。
unify(xi, yi, …) を実行した後の unify(x, y, …) は、
unify(xj, yj, …) (j > i) だけを実行したものと同じになります。
(subterm(xμ, yμ, s, t) ⇒ s_equal(s, t)) ∧ θ=μ
xμ=s ∧ yμ=t ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ unify(x1, y1, μ, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ unify(xn, yn, μ, λ) ∧ unify(x, y, μλ, θ)
xμ∈V ∧ yμ∈V ∧ xμ=yμ ∧ θ=μ
xμ∈I ∧ yμ∈I ∧ (subterm(xμ, yμ, s, t) ⇒ s_equal(s, t)) ∧ θ=μ
xμ=s ∧ yμ=t ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ unify(x1, y1, μ, σ2) ∧ … ∧ unify(xn, yn, σn, σn+1) ∧ unify(x, y, σn+1, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ unify(xn, yn, μ, σ2) ∧ … ∧ unify(xn, yn, σn, σn+1) ∧ unify(x, y, σn+1, θ)
最後の unify(x, y, σn+1, θ) は2番めの条件から θ=σn+1 となります。
xμ∈V ∧ yμ∈V ∧ xμ=yμ ∧ θ=μ
xμ=s ∧ yμ=t ∧ ¬s_equal(s, t) ∧ s_unify(s, t, λ) ∧ unify(x, y, μλ, θ)
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ ∀i∈Nn∃σi ∧ σ1=1 ∀i∈Nnunify(xi, yi, σi, σi+1) ∧ θ=σn+1
2番めの条件は、3番めの条件から呼び出されたもの以外は3番めの条件に含まれるので、
最後の unify(x, y, μλ, θ) は1番めの条件だけでよいので θ=μλ となります。
xμ∈V ∧ yμ∈V ∧ xμ=yμ ∧ θ=μ
s_unify(xμ, yμ, λ) ∧ θ=μλ
xμ∈I(f) ∧ yμ∈I(f) ∧ n=a(f) ∧ xμ≡f(x1, …, xn) ∧ yμ≡f(y1, …, yn)
∧ ∀i∈Nn∃σi ∧ σ1=1 ∀i∈Nnunify(xi, yi, σi, σi+1) ∧ θ=σn+1

単一化アルゴリズムの記述

この節では、prolog風の言語で単一化アルゴリズムを記述してみます。 Prologでは、リスト x, y が一致することを表す述語 equal(x, y) は、 次のように定義することができます。
equal([], []).
equal([Z|X], [Z|Y]) :- equal(X, Y).
E はリストの要素の集合、 L はリストの集合という意味として、 各集合を構成する写像と、集合 E の中の関係 = を以下のように定義します。
  1. nil∈L
  2. cons: E×L→L
  3. =: E×E→boolean
すると上のプログラムは次のような意味となります。
  1. equal(nil, nil)
  2. equal(x, y) ⇒ equal(cons(z, x), cons(z, y))
  3. それ以外は equal(x, y) にはならない。
これは次のように書き直すことができます。
equal(x, y)x=nil ∧ y=nil
x=cons(x1, x2) ∧ y=cons(y1, y2) ∧ x1=y1 ∧ equal(x2, y2)
Prologでは、これは
  1. P ∧ Q となっているものは、P を実行した結果が true であれば Q を実行してその結果を P ∧ Q の結果とする。 P を実行した結果が false であれば結果は false とする。
  2. P ∨ Q となっているものは、P を実行した結果が false であれば Q を実行してその結果を P ∧ Q の結果とする。 P を実行した結果が true であれば結果は true とする。
という順序で実行する半アルゴリズムとなります。

これと同じように、単一化アルゴリズムを記述してみます。 S は記号の集合、 T は項の集合、 L は項のリストの集合、 Σ は代入の集合という意味です。 各集合を構成する写像と、集合 S の中の関係 = を以下のように定義します。

  1. var: S→T
  2. func: S×L→T
  3. nil∈L
  4. cons: T×L→L
  5. id∈Σ
  6. map: S×T→Σ
  7. comp: Σ×Σ→Σ
  8. =: S×S→boolean
以下の述語を定義します。
  1. subst: S×Σ×T→boolean
  2. op: T×Σ×T→boolean
  3. notoccur: S×T→boolean
  4. s_unify: T×T×Σ→boolean
  5. unify3: T×T×Σ→boolean
  6. =: Σ×Σ→boolean (この定義は省略)
unify3 は以下の条件で生成されたもので、前節の unify2 と同等のものになります。
  1. x=var(s) ∧ y=var(s) ∧ θ=id ⇒ unify3(x, y, θ)
  2. x=var(u) ∧ y=var(v) ∧ (θ=map(u, y) ∨ θ=map(v, x)) ⇒ unify3(x, y, θ)
  3. x=var(u) ∧ y=func(v, yl) ∧ notoccur(u, y) ∧ θ=map(u, y) ⇒ unify3(x, y, θ)
  4. x=func(u, xl) ∧ y=var(v) ∧ notoccur(v, x) ∧ θ=map(v, x) ⇒ unify3(x, y, θ)
  5. x=nil ∧ y=nil ∧ θ=id ⇒ unify3(x, y, θ)
  6. x=cons(x1, x2) ∧ y=cons(y1, y2) ∧ unify3(x1, y1, λ) ∧ op(x2, λ, xs) ∧ op(y2, λ, ys) ∧ unify3(xs, ys, μ) ∧ θ=comp(λ, μ) ⇒ unify3(x, y, θ)
  7. それ以外は unify3(x, y, θ) にはならない。
subst(v, θ, y) θ=map(v, y)
θ=comp(λ, μ) ∧ subst(v, λ, x) ∧ op(x, μ, y)
op(x, θ, y) x=var(u) ∧ subst(u, θ, y)
x=func(u, xl) ∧ y=func(v, yl) ∧ op(xl, θ, yl)
op(x, θ, y) x=nil ∧ y=nil
x=cons(x1, x2) ∧ y=cons(y1, y2) ∧ op(x1, θ, y1) ∧ op(x2, θ, y2)
notoccur(v, x) x=var(u) ∧ u≠v
x=func(u, xl) ∧ notoccur(v, xl)
notoccur(v, x) x=nil
x=cons(x1, x2) ∧ notoccur(v, x1) ∧ notoccur(v, x2)
s_unify(x, y, θ) x=var(u) ∧ y=var(v) ∧ (θ=map(u, y) ∨ θ=map(v, x))
x=var(u) ∧ y=func(v, yl) ∧ notoccur(u, y) ∧ θ=map(u, y)
x=func(u, xl) ∧ y=var(v) ∧ notoccur(v, x) ∧ θ=map(v, x)
unify3(x, y, θ)x=var(s) ∧ y=var(s) ∧ θ=id
s_unify(x, y, θ)
x=func(s, xlist) ∧ y=func(s, ylist) ∧ unify3(xlist, ylist, θ)
unify3(x, y, θ)x=nil ∧ y=nil ∧ θ=id
x=cons(x1, x2) ∧ y=cons(y1, y2) ∧ unify3(x1, y1, λ) ∧
op(x2, λ, xs) ∧ op(y2, λ, ys) ∧ unify3(xs, ys, μ) ∧ θ=comp(λ, μ)

参考文献

  1. 井田哲雄: 計算モデルの基礎理論, 岩波書店, 1991.
  2. 小野寛晰: 情報科学における論理, 日本評論社, 1994.
  3. 萩谷昌己: ソフトウェア科学のための論理学, 岩波書店, 1994.
  4. 森下真一: 知識と推論, 共立出版, 1994.

2007年12月30日更新