Цели с отрицанием
Использование знака отрицания в левых частях правил, а следовательно, и в вопросах, обрабатываемых процедурой рассмотреть, представляется естественным и его следует разрешить. В качестве первой попытки можно предложить следующий способ работы с отрицанием целей:
line();% Процедура-драйвер верхнего уровня
эксперт :-
принять_вопрос( Вопрос),
% Ввести вопрос пользователя
( ответ_да( Вопрос);
% Попытка найти положительный ответ
ответ_нет( Вопрос) ).
% Если нет положительного ответа, то найти отрицательный
ответ_да( Вопрос) :-
% Искать положительный ответ на Вопрос
статус( отрицательный),
% Пока еще нет положительного ответа
рассмотреть( Вопрос, [ ], Ответ),
% Трасса пуста
положительный( Ответ), % Искать положительный ответ
статус( положительный),
% Найден положительный ответ
выдать( Ответ), nl,
write( 'Нужны еще решения?' ),
принять( Ответ1), % Прочесть ответ пользователя
Ответ1 = нет.
% В противном случае возврат к "рассмотреть"
ответ_нет( Вопрос):-
% Искать отрицательный ответ на Вопрос
retract( пока_нет_положительного_решения), !,
% Не было положительного решения?
рассмотреть( Вопрос, [ ], Ответ),
отрицательный( Ответ),
выдать( Ответ), nl,
write( 'Нужны еще решения?' ),
принять( Ответ1),
Ответ1 = нет.
% В противном случае - возврат к "рассмотреть"
статус( отрицательный) :-
assert( пока_нет_положительного_решения).
статус( положительный) :-
retract( пока_нет_положительного_решения), !; true.
принять_вопрос( Вопрос) :-
nl, write( 'Пожалуйста, спрашивайте:'), nl,
read( Вопрос).
line();
Рис. 14. 13. Оболочка экспертной системы: драйвер. Обращение
к оболочке из Пролога при помощи процедуры эксперт.
рассмотреть( не Цель, Трасса, Ответ) :- !,
рассмотреть( Цель, Трасса, Ответ1),
обратить( Ответ1, Ответ).
% Получить обратное истинностное значение
обратить( Цель это правда было Найдено,
( не Цель) это ложь было Найдено).
обратить( Цель это ложь было Найдено,
( не Цель) это правда было Найдено).
Если Цель конкретизирована, то все в порядке, если же нет, то возникают трудности. Рассмотрим, например, такой диалог:
?- эксперт.
Пожалуйста, спрашивайте:
не ( X ест мясо).
Есть (еще) решения для : Животное
да.
Животное = тигр.
В этот момент система даст ответ:
не ( тигр ест мясо) это ложь
Такой ответ нас не может удовлетворить. Источник затруднения следует искать в том, какой смысл мы вкладываем в вопросы типа
не ( X ест мясо)
В действительности мы хотим спросить: "Существует ли такой X, что X не ест мяса?" Однако процедура рассмотреть (так как мы ее определили) проинтерпретирует этот вопрос следующим образом:
(1) Существует ли такой X, что X ест мясо?
(2) Да, тигр ест мясо.
Итак,
(3) не (тигр ест мясо) это ложь.
Короче говоря, интерпретация такова - "Правда ли, что никакой X не ест мясо?" Положительный ответ мы получим, только если никто не ест мяса. Можно также сказать, что процедура рассмотреть
отвечает на вопрос так, как будто X находится под знаком квантора всеобщности:
для всех X: не (X ест мясо)?
а не квантора существования, в чем и состояло наше намерение:
для некоторого X: не (X ест мясо)?
Если рассматриваемый вопрос конкретизирован, то проблемы исчезают. В противном случае правильный способ работы с отрицаниями становится более сложным. Например, вот некоторые из возможных правил:
Для того, чтобы рассмотреть (не Цель), рассмотрите Цель, а затем:
- если Цель это ложь, то (не Цель) это правда;
- если Цель' - это некоторое решение для Цель, и Цель' - утверждение той же степени общности, что и Цель, то (не Цель) это ложь;
- если Цель' - это некоторое решение для Цель, и Цель' - более конкретное утверждение, чем Цель, то об утверждении (не Цель) нельзя сказать ничего определенного.
правило_поломки:
если
вкл( Прибор) и
прибор( Прибор) и % Конкретизация
не работает( Прибор) и
соед( Прибор, Предохр) и
доказано( цел( Предохр) )
то
доказано( неиспр( Прибор) ).
Здесь условие
прибор( Прибор)
"защищает" следующее за ним условие
не работает( Прибор)
от неконкретизированной переменной.