KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Иван Братко - Программирование на языке Пролог для искусственного интеллекта

Иван Братко - Программирование на языке Пролог для искусственного интеллекта

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Иван Братко, "Программирование на языке Пролог для искусственного интеллекта" бесплатно, без регистрации.
Перейти на страницу:

             пожалуйста'), 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?

нет.

Ответ = ложь

14.5.3. Усовершенствование процедуры ответпольз

Один из недостатков нашей процедуры ответпольз, который хорошо виден из приведенного выше диалога, — это появление на выходе системы имен, генерируемых пролог-системой, что выглядит довольно неуклюже. Символы, подобные _17, следовало бы заменить на более осмысленные слова.

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

Давайте исправим эти два дефекта. Во-первых, улучшение внешнего вида запросов системы будет основано на введении стандартного формата для каждой "запрашиваемой" цели. Для этого в отношение можно_спросить мы добавим второй аргумент, который и будет задавать этот формат, как видно из следующего примера:

можно_спросить(X ест Y, 'Животное' ест 'Что-то').

При передаче запроса пользователю каждая переменная вопроса должна быть заменена на ключевое слово, взятое из формата, например:

?- ответпольз( X ест Y, [], Ответ).


Это правда: Животное ест Что-то?

да.


Животное = питер.

Что-то = мясо.


Ответ = правда

X = питер

Y = мясо

В улучшенной версии процедуры ответпольз, показанной на рис. 14.11, такое форматирование запросов выполняется процедурой

формат( Цель, ВнешФормат, Вопрос, Перем0, Перем )

Здесь Цель — утверждение, которое нужно форматировать. ВнешФормат определяет внешний формат этого утверждения, задаваемый отношением

можно_спросить( Цель, ВнешФормат)

Вопрос — это Цель, отформатированная в соответствии с ВнешФормат. Перем — список переменных, входящих в Цель, вместе с соответствующими ключевыми словами (как указано в ВнешФормат), причем список Перем получается из списка Перем0 добавлением новых переменных. Например:

?- формат( X передает документы Y,

 'Кто' передает 'Что' 'Кому',

 Вопрос, [], Перем).


Вопрос = 'Кто' передает документы 'Кому',

 Перем = [ X/'Кто', Y/'Кому'].

Второе усовершенствование, состоящее в устранении повторных вопросов к пользователю, будет более трудным. Во-первых, все ответы пользователя следует запоминать, с тем чтобы их можно было отыскать в памяти в более поздний момент времени. Для этого достаточно сделать ответы пользователя элементами некоторого отношения и применить assert, например

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*