Книга: Программирование на языке Пролог для искусственного интеллекта

14.5.2. Процедура ответпольз

14.5.2. Процедура ответпольз

Прежде чем перейти к написанию процедуры ответпольз, давайте рассмотрим одну полезную вспомогательную процедуру

принять( Ответ)

В процессе диалога часто возникает ситуация, когда от пользователя ожидается ответ "да", "нет" или "почему". Процедура принять предназначена для того, чтобы извлечь один из этих ответов, понимая его правильно и в тех случаях, когда пользователь применяет сокращения ('д' или 'н') или делает ошибки. Если ответ пользователя непонятен, то принять просит дать другой вариант ответа.

принять( Ответ) :-
 read( Ответ1),
 означает( Ответ1, Значение), !,
  % Ответ1 означает что-нибудь?
 Ответ = Значение;                          % Да
 nl, write( 'Непонятно, попробуйте еще раз, % Нет
             пожалуйста'), nl,
 принять( Ответ). % Новая попытка
означает( да, да).
означает( д, да).
означает( нет, нет).
означает( н, нет).
означает( почему, почему).
означает( п, почему).

Следует заметить, что процедурой принять нужно пользоваться с осторожностью, так как она содержит взаимодействие с пользователем. Следующий фрагмент программы может служить примером неудачной попытки запрограммировать интерпретацию ответов пользователя:

принять( да), интерп_да( ...);
принять( нет), интерп_нет( ...);
...

Здесь, если пользователь ответит "нет", то программа попросит его повторить свой ответ. Поэтому более правильный способ такой:

принять( Ответ),
 ( Ответ = да, интерп_да( ...);
   Ответ = нет, интерп_нет( ...);
   ... )

Процедура

ответпольз( Цель, Трасса, Ответ)

спрашивает пользователя об истинности утверждения Цель. Ответ — это результат запроса. Трасса используется для объяснения в случае, если пользователь спросит "почему".

Сначала процедура ответпольз должна проверить, является ли Цель информацией, которую можно запрашивать у пользователя. Это свойство объекта Цель задается отношением

можно_спросить( Цель)

которое в дальнейшем будет усовершенствовано. Если спросить можно, то утверждение Цель выдается пользователю, который, в свою очередь, указывает истинно оно или ложно. Если пользователь спросит "почему", то ему выдается Трасса. Если утверждение Цель истинно, то пользователь укажет также значения содержащихся в нем переменных (если таковые имеются).

Все вышеизложенное можно запрограммировать (в качестве первой попытки) следующим образом:

остветпольз( Цель, Трасса, Ответ) :-
 можно_спросить( Цель), % Можно ли спрашивать
 спросить( Цель, Трасса, Ответ).
  % Задать вопрос относительно утверждения Цель
спросить( Цель, Трасса, Ответ) :-
 показать( Цель),
  % Показать пользователю вопрос
 принять(Ответ1),       % Прочесть ответ
 обработать( Ответ1, Цель, Трасса, Ответ).
  % Обработать ответ
обработать( почему, Цель, Трасса, Ответ) :-
  % Задан вопрос "почему"
 показать_трассу( Трасса),
  % Выдача ответа на вопрос "почему"
 спросить( Цель, Трасса, Ответ).
  % Еще раз спросить
обработать( да, Цель, Трасса, Ответ) :-
  % Пользователь ответил, что Цель истинна
 Ответ = правда,
 запрос_перем( Цель);
  % Вопрос о значении переменных
 спросить( Цель, Трасса, Ответ).
  % Потребовать от пользователя новых решений
обработать( нет, Цель, Трасса, ложь).
  % Пользователь ответил, что Цель ложна
показать( Цель) :-
 nl, write( 'Это правда:'),
 write( Цель), write( ?), nl.

Обращение к процедуре запрос_перем( Цель) нужно для того, чтобы попросить пользователя указать значение каждой из переменных, содержащихся в утверждении Цель:

запрос_перем( Терм) :-
 var( Терм), !, % Переменная ?
 nl, write( Терм), write( '='),
 read( Терм).   % Считать значение переменной
запрос_перем( Терм) :-
 Терм =.. [Функтор | Аргументы],
  % Получить аргументы структуры
 запрос_арг( Аргументы).
  % Запросить значения переменных в аргументах
запрос_арг( []).
запрос_арг( [Терм | Термы]) :-
 запрос_перем( Терм),
 запрос_арг( Термы).

Проведем несколько экспериментов с процедурой ответпольз. Пусть, например, известно, что пользователя можно спрашивать о наличии бинарного отношения ест:

можно_спросить( X ест Y).

(В приведенных ниже диалогах между пролог-системой и пользователем тексты пользователя даются полужирным шрифтом, а реплики пролог-системы курсивом).

?- ответпольз( питер ест мясо, [], Ответ).
Это правда: питер ест мясо? % Вопрос пользователю
да.                         % Ответ пользователя
Ответ = правда

Более интересный пример диалога (с использованием переменных) мог бы выглядеть примерно так:

?- ответпольз( Кто ест Что, [], Ответ).
Это правда: _17 ест _18?
  % Пролог дает переменным свои внутренние имена
да.
_17 =питер.
_18 =мясо.
Ответ = правда.
Кто = питер
Что = мясо; % Возврат для получения других решений
Это правда: _17 ест _18?
да.
_17 =сьюзен.
_18 = бананы.
Ответ = правда
Кто = сьюзен
Что = бананы;
Это правда : _17 ест _18?
нет.
Ответ = ложь

Оглавление книги


Генерация: 1.747. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз