Skip to content

Instantly share code, notes, and snippets.

@cametan001
Created June 2, 2010 06:34
Show Gist options
  • Select an option

  • Save cametan001/422029 to your computer and use it in GitHub Desktop.

Select an option

Save cametan001/422029 to your computer and use it in GitHub Desktop.
;;;; ルールベースの表現
(define *rule-base*
'((rule1 (and (USA) (English)) --> (Honolulu))
(rule2 (and (Europe) (France)) --> (Paris))
(rule3 (and (USA) (Continent)) --> (LosAngels))
(rule4 (and (Island) (Equator)) --> (Honolulu))
(rule5 (and (Asia) (Equator)) --> (Singapore))
(rule6 (and (Island) (Micronesia)) --> (Guam))
(rule7 (Swimming) --> (Equator))))
;;;; ワーキングメモリーの表現
(define *working-memory* '((Honolulu)))
;;;; 推論エンジンの実現
;; Step1 照合
;; 目標をルールの結論部として含むルールの集まりを探す。その
;; ようなルールがなければ、仮定は否定されたとして終了する。
;; Step2 競合の解消
;; ルールの集まりの中からルールを1つ選択する。前向き推論と
;; 同様に、ユーザーがこれを行うものとする。
;; Step3 動作
;; 選択されたルールの条件部への各要素がつぎの条件のいずれかを
;; 満たしていれば、これらを新しい目標値とし、Step1 へと戻る。
;; 1) 他のルールへの結論部として含まれている。
;; 2) ユーザーへの問い合わせによって肯定された。
;; これらの条件が満足されなければ、仮定は否定されたこととし
;; て終了する。
(define (backward-reasoning memory) ;目標を memory とする
;; Step-1 最初の目標の照合と Step-2 競合解消
(let loop ((rule (choice (pattern-matching-back memory)))
(memory memory))
;; 実行可能なルールがなければ終了
;; quit が入力されたら終了
(if (or (null? rule) (eq? rule 'quit))
'end
(let ((memory (rule-action-back rule))) ; Step-3 動作
(output-data-back memory) ; 結果の出力
(loop (choice (pattern-matching-back memory)) memory)))))
;;; 仮定が成立しないときに、そのことを出力する手続き
(define (output-data-back item)
(and (null? item)
(printn (caar *working-memory*)
" is unsuitable for you.")))
;; すべての引数を印字したのち改行する手続き
(define (printn . x)
(for-each display x)
(newline))
;;;; 競合解消 : choice
;; 選択されたルールのルール名を評価値とする
(define (choice lst) ;lst は実行可能なルールの集まり
(cond ((null? lst) '())
(else
(printn "enable rules : " lst)
(display "enter rule-name >> ")
(read)))) ;ルール名の読み込み
;;;; 照合 : pattern-matching-back
;;; states で表される結論部をもつルールを
;;; *rule-base* から探す手続き
(define (pattern-matching-back states)
;; 全体が評価値
(map get-rulename ;以降が真ならそのルールを含める
(filter (lambda (candidate) ;対象とするルール
(rule-cond? (get-action candidate) states))
*rule-base*)))
;; プロダクションルールの条件部 conds がワーキ
;; ングメモリー states に含まれているかどうかを
;; 調べる手続き
(define (rule-cond? conds states)
(or (null? conds)
(if (eq? (car conds) 'and) ;論理積であるか?
(condition-aux? (cdr conds) states)
(member conds states)))) ;単独の場合
(define (condition-aux? conds states) ;論理積の場合
(or (null? conds)
(and (member (car conds) states)
(condition-aux? (cdr conds) states))))
;;;; プロダクションルールの実現
(define (get-rulename rule) (car rule))
(define (get-cond rule) (cadr rule))
(define (get-action rule) (fourth rule))
;;;; 実行 : rule-action-back
;;; 選択されたルールの条件部が論理積の形式である
;;; かどうかに応じて、 eval-action-back を呼び出し、
;;; 新しい目標とすべき要素のリストを返す
(define (rule-action-back r) ; r は選択されたルール名
(let ((rule (get-rule r *rule-base*))) ;ルール r を取り出す
(if (null? rule)
'()
(let ((items (get-cond rule)))
(let ((item (car items)))
(eval-action-back
(if (eq? item 'and) ;論理積であるか?
(cdr items) ;論理積の場合
`(,items))
'()))))))
(define (eval-action-back items lst)
(if (null? items)
lst
(let ((item (car items)))
(let ((rules (pattern-matching-back `(,item))))
(call/cc
(lambda (k)
(eval-action-back (cdr items)
;; 条件部が他のルールの結論部に含まれている場合
(if (or (pair? rules)
;; あるいはユーザーに質問
(eq? (question item) 'y))
;; 論理積で記述されているならばつぎの条件の評価
(cons item lst)
(k '())))))))))
(define (question lst)
(and (pair? lst)
(begin
(printn "Do you feel satisfied next condition ?")
(printn (car lst)) ;条件の表示
(display "Please input 'y' or 'n' >> ")
(read)))) ; y, n の読み込み
;; ルール集合 rules の中のルール名 r の内容を評価値とする手
;; 続き
(define (get-rule r rules) ; rules はルール集合
(if (null? rules)
'() ; rules はルールベース
(let ((rule (car rules)))
(if (eq? (car rule) r) ;ルール名のチェック
rule ;選択されたルール
(get-rule r (cdr rules))))))
;; ;; 実行例
;; > (backward-reasoning *working-memory*)
;; enable rules : (rule1 rule4)
;; enter rule-name >> rule4
;; Do you feel satisfied next condition ?
;; Island
;; Please input 'y' or 'n' >> y
;; enable rules : (rule7)
;; enter rule-name >> rule7
;; Do you feel satisfied next condition ?
;; Swimming
;; Please input 'y' or 'n' >> y
;; end
;; >
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment