SICP 4.4.3 Ex. 4.69

  • 投稿日:
  • カテゴリ:

Ex. 4.69

greatがどんな動作をするか予想してみる。

入力
((great grandson) Adam ?)
出力
((great grandson) Adam Irad)
------
入力
((great great grandson) Adam ?)
出力
((great great grandson) Adam Methushael)

リストの最後が grandson であることをチェックする rule の動作の予想は

入力
(grandson-ended (great grandson))
出力
(grandson-ended (great grandson))
------
入力
(grandson-ended (son))
出力
なし

こんな感じか。

規則 great の変わっているところは、規則の名前がリストになっている点である。こんな規則が本当に作れるのか?作ったとして解釈系は実行できるのか?grandsonの前に great 以外が入っていないかチェックしなくていいのか?

気になる点は多いが、とりあえず、grandson-ended から作ってみる。

(rule (grandson-ended ?x)
      (append-to-form ?a (grandson) ?x))

こんな感じ。

次に greatの定義は

①((grandson) a) = (grandson a)
②X = (great grandson) or (great great grandson) or ... かつ (X a)= b 
  ならば  ((cons (great X)) a) = (son b) である。

こんな感じ。公理的定義というより、ほとんど帰納的定義になっている。 ①は帰納法の初期値の定義のようなもの。

rule形式にするために、②に中間変数を入れる。

②X = (great grandson) or (great great grandson) or ... かつ (X a)= b かつ (son b) = c
  ならば  ((cons (great X)) a) = c である。

ruleに置き換える

(rule ((grandson) ?a)
      (grandson ?a))

(rule ((great . ?X) ?a ?c)
      (and (son ?b ?c)
           (?X ?a ?b)
           (grandson-ended ?X)))

andの順番は工夫している。この順番以外、例えば grandson-ended を and の上のほうの行に置いたりすると無限ループしてしまう。

動かしてみる。

;;; Query input:
((great grandson) Adam ?)
;;; Query results:
((great grandson) Adam Irad)
------
;;; Query input:
((great great grandson) Adam ?)
;;; Query results:
((great great grandson) Adam Mehujael)
------
;;; Query input:
((great grandson) ?g ?ggs)
;;; Query results:
((great grandson) Irad Lamech)
((great grandson) Enoch Methushael)
((great grandson) Cain Mehujael)
((great grandson) Adam Irad)
((great grandson) Mehujael Jubal)
((great grandson) Mehujael Jabal)
------
;;; Query input:
(?relationship Adam Irad)
;;; Query results:
((great grandson) Adam Irad)

注意。最後の ?relationship の結果を得るには、Ex.4.64の無限ループする rule を DBから消しておくこと。これが残っていると、?relationship はこの rule もユニファイしようとして無限ループにはまる。(はまりました)

デバッグについて

Schemeはデバッグ機能が貧弱なので rule なんかのデバッグはとても困る。

仕方ないので apply-a-rule にデバッグプリントを入れてフレームと規則の本体を表示させている。あとは想像をたくましくするしかない。(それでも、ほとんど何が起こってるか分からない(泣)

(define (apply-a-rule rule query-pattern query-frame)
  (let ((clean-rule (rename-variables-in rule)))
    (let ((unify-result
           (unify-match query-pattern
                        (conclusion clean-rule)
                        query-frame)))
      (if (eq? #?=unify-result 'failed)
          the-empty-stream
          (qeval #?=(rule-body clean-rule)
                 (singleton-stream unify-result))))))