Точно Не проект 2 / Не books / Источник_1
.pdf390 |
Глава 7 |
|
|
|
Х имеет прямо посаженные глаза |
то Х хищник)) (setq правило7
’(если Х млекопитающее и
Х имеет копыта то Х жвачное))
(setq правило8
’(если Х млекопитающее и Х жует жвачку
то Х жвачное)) (setq правило9
’(если Х хищник и
Хжелто-коричневое и
Химеет темные пятна
то Х гепард))
(setq правило10
’(если Х хищник и
Хжелто-коричневое и
Хполосатое и
Химеет черные полосы то Х тигр))
(setq правило11
’(если Х жвачное и
Хдлинношеее и
Хдлинноногое и
Хжелто-коричневое и
Химеет темные пятна то Х жираф))
(setq правило12
’(если Х жвачное и
Хполосатое и
Химеет черные полосы
то Х зебра))
(setq правило13
’(если Х птица и
Хне летает и
Хдлинношеее и
Хдлинноногое и
Хчерно-белое то Х страус))
(setq правило14
’(если Х птица и
X не летает и
Хплавает и
Хчерно-белое
то Х пингвин))
(setq правило15
’(если Х птица и
Х хорошо летает
Экспертные системы |
391 |
|
|
то Х альбатрос))
С целью упрощения программы преобразуем базу знаний из исходной формы в список, элементами которого являются структуры:
(defstruct rule |
;имя структуры |
имя |
; имя правила |
условия |
; список предпосылок правила |
выводы) |
; список заключений правила |
Напомним, что создать экземпляр структуры в языке Лисп можно с помощью функции-конструктора, имя которой образуется из слова MAKE и имени структуры. Например:
(make-rule
: имя ’правило15
:условия ’( (Х птица) (Х хорошо летает))
:выводы ’((Х альбатрос)) )
Вэтом случае условия и заключения правила задаются подсписками, каждый из которых выступает в роли образца, сопоставляемого с фактами рабочей памяти. Преобразование базы знаний в список, элементами которого
являются указанные структуры, выполним |
с помощью функции |
ПРЕОБРАЗОВАТЬ: |
|
(defvar *правила*)
(setq *правила* (преобразовать *база-знаний*))
Здесь значением глобальной переменной *ПРАВИЛА* будет список из структур. Функция ПРЕОБРАЗОВАТЬ определяется следующим образом
[49]:
(defun преобразовать (база-знаний)
(mapcar #’преобразовать-правило база-знаний ))
;;преобразует правило из формы в виде списка в структуру
(defun преобразовать-правило (имя) (let (( правило (eval имя)))
(make-rule
:имя имя
:условия (prem правило)
:выводы (concl правило))))
;;возвращает условия правила в виде списка, ;;элементами которого являются образцы
(defun prem (правило)
Экспертные системы |
393 |
|
|
Переменная *ГИПОТЕЗА* представляет список целевых утверждений, которые система будет пытаться последовательно доказывать. Следовательно, в основной программе должна вызываться рекурсивная функция SOLVE, последовательно обрабатывающая элементы списка *ГИПОТЕЗЫ*
[49]:
;;; главная программа |
|
|
|
(defvar |
*факты*) |
; |
список фактов |
(defvar |
*вопросы*) |
; |
список фактов, о которых |
(setq *факты* nil) |
; |
задавались вопросы пользователю |
|
|
|
||
(setq *вопросы* nil) |
|
|
|
;; экспертная система классификации животных |
|||
(defun |
expert () |
|
|
(solve *гипотезы*))
;; функция последовательно проверяет гипотезы
(defun solve (гипотезы)
(cond
((null гипотезы) “Не могу доказать ни одну гипотезу”)
((back-prove |
; вызов функции доказательства |
|
(car гипотезы)) |
|
|
(car гипотезы)) |
; |
результат |
(t (solve (cdr гипотезы))))) |
; |
следующая попытка |
Рассмотрим функцию BACK-PROVE, осуществляющую обратный вывод. Функция базируется на следующих правилах:
1)если гипотеза уже имеется в списке фактов (рабочей памяти), то она доказана;
2)если гипотезы нет в списке фактов, то все правила, которые могут подтвердить гипотезу, помещаются в список КАНДИДАТЫ, и если какоелибо из правил списка КАНДИДАТЫ непосредственно выполняется на множестве известных фактов, то гипотеза доказана, иначе предпринимается попытка доказать все условия одного из правил списка
КАНДИДАТЫ, применив рекурсивно рассматриваемую процедуру обратного вывода;
3)если условие, которое требуется доказать, не выводится с помощью правил, то необходимо запросить его значение у пользователя; если условие выполняется, то добавить его к списку фактов.
Выполнимость правила на множестве фактов будем проверять с по-
мощью функции TEST-RULE:
(defun test-rule (правило)
(match1 (rule-условия правило) *факты*))
Экспертные системы |
395 |
|
|
(setq *факты* (union (list гипотеза) *факты*))
;добавляем гипотезу к списку вопросов независимо от ответа (push гипотеза *вопросы*) t)
(t (push гипотеза *вопросы*) nil))))))
;;формирование списка правил-кандидатов, способных
;;подтвердить гипотезу
(defun поиск-кандидатов (гипотеза) (mapcan #’(lambda (x)
(if (member гипотеза (rule-выводы x) : test #’equal) (list x)))
*правила*))
;;проверяет, можно ли непосредственно доказать
;;гипотезу с помощью какого-либо правила-кандидата (defun непосредственно(гипотеза кандидаты)
(cond
((null кандидаты) nil)
((null *факты*) nil)
;если правило применимо, то добавляем его заключение к фактам
((test-rule (car кандидаты)) (add-concl (car кандидаты)))
(t (непосредственно гипотеза (cdr кандидаты)))))
;;проверяет, можно ли рекурсивно доказать гипотезу с
;;помощью какого-либо правила-кандидата
(defun рекурсивно(гипотеза кандидаты) (cond
((null кандидаты) nil)
; проверить возможность доказательства условий правила ((test-условия (rule-условия (car кандидаты))) ; новая подцель
(add-concl (car кандидаты)))
(t (рекурсивно гипотеза (cdr кандидаты)))))
;;проверяет возможность доказательства всех условий
;;правила с помощью функции обратного вывода (defun test-условия (условия)
(every # ’back-prove условия))
Процесс классификации животных по внешним признакам начинается с вызова основной функции EXPERT. Ниже приведен возможный диалог с системой:
(expert) |
|
Верно, что: Х имеет шерсть ? |
; вопрос |
Нет |
; ответ |
Верно, что: Х кормит детенышей молоком ? |
|
Нет |
|
Верно, что: Х имеет перья ? |
|
Экспертные системы |
399 |
|
|
правило 4: если плита(холодная) и лампа(не_светится)
то тока(нет).
правило 5: если лампа(не_светится) и плита(горячая)
то лампа(не_исправна).
:
правило1 если
то
инагреватель(неисправен)
лампа(светится) плита(холодная)
Рисунок 7.5 – Структура, соответствующая правилу
В ходе вывода метаинтерпретатор должен установить причину неисправности, проверяя различные гипотезы. Представим возможные гипотезы в форме:
Имя_факта : Факт.
Тогда в соответствии с введенными правилами база данных возможных причин неисправности (гипотез) запишется в виде:
h1 : причина(нагреватель(неисправен)). h2 : причина(выключатель(не_включен)). h3 : причина(напряжения(нет)).
h4 : причина(лампа(неисправна)).
Кроме этого, перечислим наблюдаемые признаки, на основе которых метаинтерпретатор должен установить причину неисправности.
h1 : признак(лампа(светится)).
h2 : признак(плита(холодная)). h3 : признак(лампа(не_светится)). h4 : признак(плита(горячая)).