Экспертная система спрашивает у пользователя недостающую информацию.
Общепринято представлять экспертную систему в виде базы знаний и механизма вывода. Механизм вывода будет построен путем усовершенствования метаинтерпретатора (программа 4). Базы знаний, образованные средствами Пролога, являются выполняемыми программами. Рассмотрим упрощенный пример такой базы знаний - база знаний "Болезни". Для более наглядного инфиксного изображения предикатов специально введены операторы: ‘-рекомендовано', 'имеет', 'имеет симптом', 'имеет признак'.
:- op(100,xfx,['- рекомендовано','имеет','имеет симптом',
'имеет признак']).
X '- рекомендовано' 'лечь в постель и принять аспирин':-
X 'имеет' 'простуда',
not( X 'имеет' 'уязвимый возраст').
X '- рекомендовано' 'вызвать врача':-
X 'имеет' 'простуда',
X 'имеет' 'уязвимый возраст'.
X '- рекомендовано' 'вызвать врача':-
X 'имеет' 'острый фарингит'.
X '- рекомендовано' 'лечь в постель и принять аспирин':-
X 'имеет' 'грипп'.
X 'имеет' 'простуда':-
X 'имеет симптом' 'мышечные боли',
X 'имеет симптом' 'лихорадка'.
X 'имеет' 'уязвимый возраст':-
X 'имеет признак' 'моложе 8 лет'.
X 'имеет' 'уязвимый возраст':-
X 'имеет признак' 'старше 60 лет'.
X 'имеет' 'острый фарингит':-
X 'имеет симптом' 'лихорадка',
X 'имеет симптом' 'нарывы в горле'.
X 'имеет' 'грипп':-
X 'имеет симптом' 'насморк',
X 'имеет симптом' 'мышечные боли',
not(X 'имеет симптом' 'лихорадка').
hy(X,Y):-
member(Y,['лечь в постель и принять аспирин','вызвать врача']),
X '- рекомендовано' Y.
Предикат hy является целью для экспертной системы с данной базой знаний, с его помощью пользователь пытается выяснить справедливость гипотез ’лечь в постель и принять аспирин’ и ’вызвать врача’. Попытаемся получить рекомендацию для Боба:
?- solve(hy(bob,Y)).
No
В базе знаний не заложены конкретные симптомы, предполагается, что экспертная система может задавать пользователю вопросы в случае нехватки информации.
Мы вводим специальную процедуру askable/1, которая в случае безуспешного решения цели интерпретатором может направить её на рассмотрение пользователю.
% программа 5
:- dynamic untrue/1.
solve(true):-!.
solve((A,B)):-!,
solve(A),
solve(B).
solve(not(A)):-!,
not(solve(A)).
solve(A):-
not system(A),
clause(A,B),
solve(B).
solve(A):-
system(A),
A.
solve(A):-
askable(A),
not known(A),
ask(A,Answer),
respond(Answer,A).
system(is(_,_)).
system(_=_).
system(_<_).
system(_>_).
system(write(_)).
system(nl).
system(member(_,_)).
ask(A,Answer):-
display_query(A),
read(Answer).
respond(yes,A):-
assert(A).
respond(no,A):-
assert(untrue(A)),fail.
known(A):-A,!.
known(A):-
untrue(A).
display_query(A):-
write(A),
write('?').
Предикат askable определяет какие вопросы будут заданы пользователю. Чтобы избежать повторения одних и тех же вопросов, программа записывает ответы на вопросы, что обеспечивается предикатом respond . Если на вопрос A последовал ответ yes, то в программу вводится факт A. Если же получен ответ no, то в программу вводится факт untrue(A). Эта информация используется предикатом known, чтобы избежать задания вопросов, ответы на которые уже известны программе. Директива dynamic для untrue добавлено для того, чтобы избежать предупреждение Пролога об отсутствии определения untrue.
Дополняем базу знаний предикатом askable и директивой dynamic для предикатов ‘имеет симптом’ и ‘имеет признак’.
dynamic 'имеет симптом'/2, 'имеет признак'/2.
askable(_ 'имеет симптом' _).
askable(_ 'имеет признак' _).
Теперь получим рекомендации для Боба:
?- solve(hy(bob,Y)).
bob имеет симптом мышечные боли? yes.
bob имеет симптом лихорадка? yes.
bob имеет признак моложе 8 лет? no.
bob имеет признак старше 60 лет? no.
Y = 'лечь в постель и принять аспирин' ;
bob имеет симптом насморк? yes.
bob имеет симптом нарывы в горле? yes.
Y = 'вызвать врача' ;
No
Повторный запрос для Боба приводит сразу к тому же ответу:
?- solve(hy(bob,Y)).
Y = 'лечь в постель и принять аспирин' ;
Y = 'вызвать врача' ;
No
|