簡単な人工知能もどき
まぐまぐ! - 読みたいメルマガ、きっと見つかる。で出されている問題を、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