отрицательный( Ответ) :-
истинность( Ответ, ложь).
Рис. 14.10. Основная процедура оболочки экспертной системы.
14.5.2. Процедура ответпольз
Прежде чем перейти к написанию процедуры ответпольз
, давайте рассмотрим одну полезную вспомогательную процедуру
принять( Ответ)
В процессе диалога часто возникает ситуация, когда от пользователя ожидается ответ 'да', 'нет' или 'почему'. Процедура принять
предназначена для того, чтобы извлечь один из этих ответов, понимая его правильно и в тех случаях, когда пользователь применяет сокращения ('д' или 'н') или делает ошибки. Если ответ пользователя непонятен, то принять
просит дать другой вариант ответа.
принять( Ответ) :-
read( Ответ1),
означает( Ответ1, Значение), !,
% Ответ1 означает что-нибудь?
Ответ = Значение; % Да
nl, write( 'Непонятно, попробуйте еще раз, % Нет
пожалуйста'), nl,
принять( Ответ). % Новая попытка
означает( да, да).
означает( д, да).
означает( нет, нет).
означает( н, нет).
означает( почему, почему).
означает( п, почему).
Следует заметить, что процедурой принять
нужно пользоваться с осторожностью, так как она содержит взаимодействие с пользователем. Следующий фрагмент программы может служить примером неудачной попытки запрограммировать интерпретацию ответов пользователя:
принять( да), интерп_да( ...);
принять( нет), интерп_нет( ...);
...
Здесь, если пользователь ответит 'нет', то программа попросит его повторить свой ответ. Поэтому более правильный способ такой:
принять( Ответ),
( Ответ = да, интерп_да( ...);
Ответ = нет, интерп_нет( ...);
... )
Процедура
ответпольз( Цель, Трасса, Ответ)
спрашивает пользователя об истинности утверждения Цель
. Ответ
— это результат запроса. Трасса
используется для объяснения в случае, если пользователь спросит 'почему'.
Сначала процедура ответпольз
должна проверить, является ли Цель
информацией, которую можно запрашивать у пользователя. Это свойство объекта Цель
задается отношением
можно_спросить( Цель)
которое в дальнейшем будет усовершенствовано. Если спросить можно, то утверждение Цель
выдается пользователю, который, в свою очередь, указывает истинно оно или ложно. Если пользователь спросит 'почему', то ему выдается Трасса
. Если утверждение Цель
истинно, то пользователь укажет также значения содержащихся в нем переменных (если таковые имеются).
Все вышеизложенное можно запрограммировать (в качестве первой попытки) следующим образом:
остветпольз( Цель, Трасса, Ответ) :-
можно_спросить( Цель), % Можно ли спрашивать
спросить( Цель, Трасса, Ответ).
% Задать вопрос относительно утверждения Цель
спросить( Цель, Трасса, Ответ) :-
показать( Цель),
% Показать пользователю вопрос
принять(Ответ1), % Прочесть ответ
обработать( Ответ1, Цель, Трасса, Ответ).
% Обработать ответ
обработать( почему, Цель, Трасса, Ответ) :-
% Задан вопрос 'почему'
показать_трассу( Трасса),
% Выдача ответа на вопрос 'почему'
спросить( Цель, Трасса, Ответ).
% Еще раз спросить
обработать( да, Цель, Трасса, Ответ) :-
% Пользователь ответил, что Цель истинна
Ответ = правда,
запрос_перем( Цель);
% Вопрос о значении переменных
спросить( Цель, Трасса, Ответ).
% Потребовать от пользователя новых решений
обработать( нет, Цель, Трасса, ложь).
% Пользователь ответил, что Цель ложна
показать( Цель) :-
nl, write( 'Это правда:'),
write( Цель), write( ?), nl.
Обращение к процедуре запрос_перем( Цель)
нужно для того, чтобы попросить пользователя указать значение каждой из переменных, содержащихся в утверждении Цель
:
запрос_перем( Терм) :-
var( Терм), !, % Переменная ?
nl, write( Терм), write( '='),
read( Терм). % Считать значение переменной
запрос_перем( Терм) :-
Терм =.. [Функтор | Аргументы],