Процедура useranswer представляет собой реализацию средства "запрос к пользователю". В случае необходимости эта процедура запрашивает у пользователя информацию, а также объясняет ему, для чего она потребовалась. Прежде чем приступить к разработке процедуры useranswer, рассмотрим следующую полезную вспомогательную процедуру: getreplyС Reply)
В ходе диалога от пользователя часто требуется, чтобы он ответил словом "yes", "по" или "why". Назначение процедуры get reply состоит в получении подобного ответа от пользователя, а также в правильном преобразовании этого ответа, если пользователь вводит сокращение ("у" или "п") или допускает опечатку. А если ответ пользователя невозможно понять, то getreply запрашивает у него другой ответ.
Следует отметить, что процедура getreply должна использоваться с осторожностью, поскольку в ней предусмотрено взаимодействие с пользователем с помощью предикатов read и write, поэтому она может трактоваться только процедурно, а не декларативно. Например, если процедура getreply будет вызвана на выполнение следующим образом: getreplyl yes)
а пользователь введет "по", то процедура не сможет сопоставить два разных атома и выдаст ответ; "Answer unknown, try again please" (Ответ непонятен, сделайте, пожалуйста, еще одну попытку). Поэтому процедуру getreply следует вызывать с неконкретизированным параметром, например, как показано ниже. getreplyt Reply),
.-(Reply - yes, interpret yes (...! Reply = no, interpret»©!...}
Процедура useranswer; Goal, Trace, Answer)
запрашивает у пользователя информацию, касающуюся цели Goal, а результатом этого запроса является ответ Answer. Трассировка Trace используется для выдачи объяснения в том случае, если пользователь спрашивает "why". Процедура useranswer должна вначале проверить, относится ли Goal к информации того типа, о которой можно спрашивать пользователя. В данном командном интерпретаторе цели такого рода обозначены как "askable" (запрашиваемые). Для начала предположим, что запрашиваемые сведения определены с помощью следующего отношения; askable С Goal)
Это определение будет уточнено позднее. Если цель Goal относится к типу "askable", то эта цель отображается и пользователь должен указать, является ли она истинной или ложной. В том случае, если пользователь спрашивает, для чего потребовалась эта информация, введя вопрос "why", отображается трассировка Trace.
Глава 16. Командный интерпретатор экспертной системы 369
Цель Goal является истинной, если пользователь задает также необходимые значения переменных в цели Goal (при условии, что они имеются). Первая попытка ре-шить эти задачи в программе может состоять в следующем:
useranswer Goal, Trace, Answer):-
askable [ Goal), ask(Goal, Trace, Answer). |
пользователю с запросом, |
запросом, |
* Можно ли обращаться к % касающимся цели Goal? % Обратиться к пользователю касающимся цели Goal
Вывести запрос к пользователю Прочитать ответ пользователя |
ask(Goal, Trace, Answer):-introduce! Goal), getreply t Reply), process! Reply, Goal, Trace,
Answer).» Обработать ответ
process( |
Goal, Trace, Answer) |
для чего |
% Пользователь спросил,
% нужна эта информация
showtraceC Trace), ask< Goal, Trace, Answer). process! yes, Goal, Trace, Answer) Answer - true, askvars[ Goal) |
i Показать трассировку
% Снова вывести запрос
что цель Goal |
% Пользователь сообщил,
% является истинной
i Задать вопрос, касающийся переменных
ask(Goal, Trace, Answer). * Запросить дополнительные решения process) no. Goal, Trace, false). % Пользователь сообщил, что цель Goal
i является ложной
introduce! Goal):-
nl, write! Ts it true: '), write 1 Goal), writet?), nl.
После вызова процедуры askvars { Goal) пользователь получает запрос ввести значение каждой переменной в цели Goal, следующим образом:
askvars (Terra):-
var(Term),!, % Переменная?
nl, write! Term), write (' — '),
read(Term), I Прочитать значение переменной
askvars t Terra):-
Term ■=.. [Functor Args], % Получить параметры структуры
askarglist(Args). I Задать вопрос, касающийся переменных в параметрах
askarglist([)).
askarglist([Term ] Terms]):-
askvars(Term),
askarglist! Terms).
Проведем несколько экспериментов с процедурой useranswer. Например, предположим, что в виде "askable" объявлено бинарное отношение eats, как показано ниже. askable[ X eats Y).
пользователем текст, введенный |
Б следующем диалоге между системой Prolog пользователем, обозначен полужирным шрифтом.
?- useranswert peter eats meat, [], Answer).
пользователю |
% Ответ пользователя |
Is it true: peter eats meat? * Запрос
yes.
true |
Answer
Более интересный пример, в котором используются переменные, может выглядеть
следующим образом:
?- -jserar.swer. Who eats What, Is it true: _17 eats _1S?
yes.
_17 = peter. 18 = meat.
[), Answer).
% Система Prolog присваивает переменным % внутренние имена
% Запрос, касающийся переменных
Часть II. Применение языка Prolog в области искусственного интеллекта
Answer = true
Who = peter
What = meat % Перебор с возвратами для получения дополнительных решений
Is it true: _17 eats _18?
yes.
_17 = susan.
_18 = bananas.
Answer = true
Who = susan
What = bananas;
Is it true: eats _18?
no.
Answer = false