« パターン照合(1) | メイン | 専門家による新型インフルエンザへの対応策の提言 »

ユニフィケーション照合アルゴリズム

前回(パターン照合(1))の続き。

Javaによる知能プログラミング入門』の「2.探索とパターン照合」にあるパターン照合プログラムのソースコードをPythonで実装してみました。

前回のパターン照合プログラムは文字列とパターンが一致するかをテストしました。
今回のプログラムでは、2つのパターンが矛盾のない変数代入によって同一と判断できるかをテストします。

次のパターンをテストします。

print Unify().unify("Takayuki", "Takayuki")
print Unify().unify("Takayuki", "Takoyuki")
print Unify().unify("?x am Takayuki", "I am Takayuki")
print Unify().unify("?x is ?x", "a is b")
print Unify().unify("?x is ?x", "a is a")
print Unify().unify("?x is a", "b is ?y")
print Unify().unify("?x is a", "?y is ?x")

ユニフィケーション照合アルゴリズムというらしい。

関数をまたかってやりとりする変数(vars,buffer1,buffer2)があるので、クラスにしました。
読みやすくなったかどうかは、微妙なところです。

#! /usr/bin/python
# -*- coding: Shift_JIS -*-
import re

class Unify(object):
    def __init__(self):
        self.vars = {} #変数と値の辞書

    def unify(self, str1, str2):
        print str1
        print str2

        # 同じなら成功
        if str1 == str2: return True

        # 各々トークンに分ける
        r = re.compile('\s')
        self.buffer1 = r.split(str1)
        self.buffer2 = r.split(str2)

        # 数が異なったら失敗
        if len(self.buffer1) != len(self.buffer2): return False

        for i in range(len(self.buffer1)):
            if not self.token_matching(self.buffer1[i], self.buffer2[i]):
                return False

        print self.vars
        return True

    def token_matching(self, token1, token2):
        if token1 == token2: return True
        if var(token1) and not var(token2): return self.var_matching(token1, token2)
        if not var(token1) and var(token2): return self.var_matching(token2, token1)
        if var(token1) and var(token2): return self.var_matching(token1, token2)
        return False

    def var_matching(self, vartoken, token):
        if self.vars.has_key(vartoken):
            if token == self.vars[vartoken]:
                return True
            else:
                return False
        else:
            self.replace_buffer(vartoken, token);
            if self.vars.has_key(vartoken):
                self.replace_bindings(vartoken,token)
            self.vars[vartoken] = token
        return True

    def replace_buffer(self, pre_string, post_string):
        def replace_pre(x):
            if pre_string == x:
                return post_string
            else:
                return x
        self.buffer1 = map(replace_pre, self.buffer1)
        self.buffer2 = map(replace_pre, self.buffer2)

    def replace_bindings(self, pre_string, post_string):
        for key in self.vars.keys():
            if pre_string == self.vars[key]:
                self.vars[key] = post_string

def var(str):
    """ strは変数か。先頭が ? なら変数。 """
    return str.startswith("?")

if __name__ == "__main__":
    print Unify().unify("Takayuki", "Takayuki")
    print Unify().unify("Takayuki", "Takoyuki")
    print Unify().unify("?x am Takayuki", "I am Takayuki")
    print Unify().unify("?x is ?x", "a is b")
    print Unify().unify("?x is ?x", "a is a")
    print Unify().unify("?x is a", "b is ?y")
    print Unify().unify("?x is a", "?y is ?x")

トラックバック

このエントリーのトラックバックURL:
http://www.gesource.jp/mt/mt-tb.cgi/975

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

About

2009年05月20日 22:04に投稿されたエントリーのページです。

ひとつ前の投稿は「パターン照合(1)」です。

次の投稿は「専門家による新型インフルエンザへの対応策の提言」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Powered by
Movable Type 3.35