簡単な人工知能もどき

まぐまぐ! - 読みたいメルマガ、きっと見つかる。で出されている問題を、Rubyでやってみた。
以下はリンク先からの引用。

例えば、
ソクラテス」は「人間」である。
「人間」は「必ず死ぬ存在」である。
という2つの知識が与えられて、
ソクラテス」は「必ず死ぬ存在」である。
という結論(?)を導くようなスクリプトを作ります。

簡単にいうと三段論法AIみたいな。


僕の書いたスクリプトでは、以下のような知識が与えられると、

「ソクラテス」は「人間」である。
「人間」は「植物」ではない。
「動物」は「必ず死ぬ存在」である。
「ミドリムシ」は「葉緑素を持っている存在」である。
「ミドリムシ」は「動物」である。
「人間」は「動物」である。
「葉緑素を持っている存在」は「光合成を行うことができる存在」である。


以下のような出力をする。
結城さんの書いたスクリプトは、
結論だけを出力するようだけど、
僕のは結論も含めて、得られた知識全てを出力する。
書いてて思ったけど、僕のやり方の方がたぶん難しい。

「動物」は「必ず死ぬ存在」なんだにょ。
「ミドリムシ」は「動物」なんだにょ。
「ミドリムシ」は「光合成を行うことができる存在」なんだにょ。
「ミドリムシ」は「葉緑素を持っている存在」なんだにょ。
「ミドリムシ」は「必ず死ぬ存在」なんだにょ。
「ソクラテス」は「動物」なんだにょ。
「ソクラテス」は「植物」じゃないにょ。
「ソクラテス」は「必ず死ぬ存在」なんだにょ。
「ソクラテス」は「人間」なんだにょ。
「葉緑素を持っている存在」は「光合成を行うことができる存在」なんだにょ。
「人間」は「動物」なんだにょ。
「人間」は「植物」じゃないにょ。
「人間」は「必ず死ぬ存在」なんだにょ。


スクリプトはこんな感じ。
あんまりキレイじゃない。

class AI
  def initialize
    @know = Hash.new # 知識
  end

  def input(str)
    return if /^#/ =~ str

    if /(.*)」は「(.*)(.*)/s =~ str
      former = $1 # 前者
      latter = $2 # 後者
      ending = $3 # 語尾

      unless @know[former]
        @know[former] = Hash.new
      end

      flg = nil
      flg = true if /である/ =~ ending
      flg = false if /ではない/ =~ ending

      unless flg == nil
        @know[former][latter] = flg
        # 三段論法
        syllogism(former, latter, flg)
      end
    end
  end

  def output
    # 出力をする前に最終チェックをする。
    # これを怠ると、例えば以下のような3文を入力したときに
    # 1.「ソクラテス」は「人間」である。
    # 2.「動物」は「必ず死ぬ存在」である。
    # 3.「人間」は「動物」である。
    # 1.と2.を繋げることができない。
    @know.each{|former, v|
      v.each{|latter, flg|
        syllogism(former, latter, flg)
      }
    }

    @know.each{|former, v|
      v.each{|latter, flg|
        print "#{former}」は「#{latter}" 
        puts flg ? "なんだにょ。" : "じゃないにょ。"
      }
    }
  end  

  # 三段論法
  def syllogism(former, latter, flg)
    # 「ソクラテス」は「人間」である。
    # 「人間」は「植物」ではない。の2つから、
    # 「ソクラテス」は「植物」ではない。を導く
    @know.each{|fo, v|
      v.each_key{|la| 
        # 1つ目の後者と2つ目の前者が一致しなかったらスルー
        next unless la == former
        @know[fo][latter] = flg
      }
    }
  end
end


ai = AI.new

while str = gets
  ai.input(str)
end

ai.output