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