То, что по силам читателю, предоставь ему самому.
Людвиг Витгенштейн
Последний пример использования метаинтерпретаторов для экспертных систем связан с применением механизма рассуждений в условиях неопределенности. Причиной для введения такого механизма является наличие неопределенной информации - правил и фактов. Дедуктивный вывод при неопределенных предположениях должен приводить к неопределенным заключениям. Существует несколько способов представления неопределенности в правилах и способов вычисления неопределенности заключений. Основное требование состоит в том, что в предельном случае, когда все правила определенные, поведение системы повторяло стандартный механизм дедукции.
Остановимся на следующем подходе. С каждым правилом или фактом свяжем коэффициент определенности c, 0< c <= 1. Логическая программа с неопределенностями - это множество пар , где Clause -предложение, а Factor - коэффициент определенности. Оболочка экспертной системы, работающая в условиях неопределенности, получена путем непосредственного усовершенствования программы 7. Отношение solve(Goal,Proof,Certainty) истинно, когда цель Goal удовлетворена с определенностью Certainty, а Proof - дерево доказательства Goal. В программе предполагается, что предложения с коэффициентами определенности представлены с использованием предиката clause_cf(A,B,CF).
% программа 10
:- multifile system/1, askable/1, clause_cf/3.
:- dynamic untrue/1, askable/1, clause_cf/3.
% введем стартовый предикат
expert(X):-
solve(X,[],C),nl,
write('доказано с уверенностью '),
write(C).
solve(true,_,1):-!.
solve((A,B),Rules,C):-!,
solve(A,Rules,C1),
solve(B,Rules,C2),
C is min(C1,C2).
solve(not(A),_,1):-!,
not(solve(A,_,_)).
solve(A,Rules,C):-
not system(A),
clause(A,B),
solve(B,[rule(A,B)|Rules],C).
solve(A,Rules,C):-
not system(A),
clause_cf(A,B,C1),
solve(B,[rule(A,B)|Rules],C2),
C is C1*C2.
solve(A,_,1):-
system(A),
A.
solve(A,Rules,C):-
askable(A),
not known(A),
ask(A,Answer),
respond(Answer,A,Rules,C).
system(is(_,_)).
system(_=_).
system(_<_).
system(_>_).
system(write(_)).
system(nl).
ask(A,Answer):-
display_query(A),
read(Answer).
respond(yes,A,_,1):-
assert(A).
respond(no,A,_,0):-
assert(untrue(A)),fail.
respond(why,A,Rules,C):-
var(Rules),!,
write(' хочу использовать ложность '),
write(A),nl,
ask(A,Answer),
respond(Answer,A,[],C).
respond(why,A,[Rule|Rules],C):-
write(' хочу воспользоваться правилом:'),
display_rule(Rule),
ask(A,Answer),
respond(Answer,A,Rules,C).
respond(why,A,[],C):-
write(' <== возможности объяснения исчерпаны '),nl,
ask(A,Answer),
respond(Answer,A,[],C).
% добавляем правила для respond
respond(C,A,_,C):-
number(C),C>0,
assert(clause_cf(A,true,C)).
respond(0,A,_,0):-
assert(untrue(A)),fail.
% добавляем правило для known
known(A):-
clause_cf(A,true,_),!.
known(A):-A,!.
known(A):-
untrue(A).
display_query(A):-
write(A),
write('?').
display_rule(rule(A,B)):-
nl,write('Если '),
write_conjunction(B),
write(' то '),
write(A),nl.
write_conjunction((A,B)):-
!,write(A),write(' и '),
write_conjunction(B).
write_conjunction(A):-
write(A),nl.
База знаний “Болезни” в отдельном файле:
:- op(100,xfx,['- рекомендовано','имеет','имеет симптом',
'имеет признак']).
:-dynamic 'имеет симптом'/2, 'имеет признак'/2.
clause_cf(
X '- рекомендовано' 'лечь в постель и принять аспирин',
(X 'имеет' 'простуда',
not( X 'имеет' 'уязвимый возраст')),
0.9).
X '- рекомендовано' 'вызвать врача':-
X 'имеет' 'простуда',
X 'имеет' 'уязвимый возраст'.
X '- рекомендовано' 'вызвать врача':-
X 'имеет' 'острый фарингит'.
clause_cf(
X '- рекомендовано' 'лечь в постель и принять аспирин',
X 'имеет' 'грипп',
0.7).
clause_cf(
X 'имеет' 'простуда',
(X 'имеет симптом' 'мышечные боли',
X 'имеет симптом' 'лихорадка'),
0.8).
X 'имеет' 'уязвимый возраст':-
X 'имеет признак' 'моложе 8 лет'.
X 'имеет' 'уязвимый возраст':-
X 'имеет признак' 'старше 60 лет'.
clause_cf(
X 'имеет' 'острый фарингит',
(X 'имеет симптом' 'лихорадка',
X 'имеет симптом' 'нарывы в горле'),
0.9).
clause_cf(
X 'имеет' 'грипп',
(X 'имеет симптом' 'насморк',
X 'имеет симптом' 'мышечные боли',
not(X 'имеет симптом' 'лихорадка')),
0.8).
askable(_ 'имеет симптом' _).
askable(_ 'имеет признак' _).
hy(X,Y):- member(Y,['лечь в постель и принять аспирин',
'вызвать врача']), X '- рекомендовано' Y.
system(member(_,_)).
Протокол работы:
?- expert(hy(bob,Y)).
bob имеет симптом мышечные боли? 0.9.
bob имеет симптом лихорадка? 0.8.
bob имеет признак моложе 8 лет? no.
bob имеет признак старше 60 лет? 0.
доказано с уверенностью 0.576000
Y = 'лечь в постель и принять аспирин' ;
bob имеет симптом насморк? yes.
bob имеет симптом нарывы в горле? 1.
доказано с уверенностью 0.720000
Y = 'вызвать врача' ;
No
?- expert(hy(cat,Y)).
cat имеет симптом мышечные боли? no.
cat имеет симптом насморк? 0.7.
cat имеет симптом лихорадка? 0.1.
cat имеет симптом нарывы в горле? 0.5.
доказано с уверенностью 0.090000
Y = 'вызвать врача' ;
No
|